Set-up

rm(list = ls())
library(dplyr)
library(wesanderson)
library(GillespieSSA)
library(tidyverse)

Model Parameter estimation

Agta Hunter-Gatherer Demography

Information regarding births, deaths and population size were obtain from a study conducted by Headland et al., (2011). Authors conducted a census-like survey of the

agta_demo <- read.csv("AgtaPopDynamics_Headland2007.csv")

ggplot(agta_demo, aes(x=Year)) +
  geom_line(aes(y=PopSize), colour = wes_palettes$Darjeeling1[1]) +
  geom_line(aes(y=Births), colour = wes_palettes$Darjeeling1[2]) +
  geom_line(aes(y=Deaths), colour = wes_palettes$Darjeeling1[3]) +
  theme_bw()

Population Size

hist(agta_demo$PopSize)

summary(agta_demo$PopSize)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  133.0   177.0   213.0   211.4   228.0   295.0 

Births

hist(agta_demo$Births)

summary(agta_demo$Births)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
   4.00    8.00   10.00   10.33   12.25   15.00       1 

Deaths

hist(agta_demo$Deaths)

summary(agta_demo$Deaths)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
  2.000   5.000   7.000   7.683  10.000  23.000       1 

Birth/Death rate per person per day

agta_demo <- agta_demo %>%
  mutate(Birth_rate = Births/(Female*2),
         Birth_rate_daily = (1 + Birth_rate) ^ (1/365) - 1,
         Death_rate = (Deaths/PopSize),
         Death_rate_daily = (1 + Death_rate) ^ (1/365) - 1,
         PopChange = (diff = PopSize - lag(PopSize, default = first(PopSize))),
         PopChange_rate = abs(PopChange)/PopSize,
         PopChange_rate_daily = (1 + PopChange_rate) ^ (1/365) - 1)
head(agta_demo)


hist(agta_demo$Birth_rate)

hist(agta_demo$Death_rate)


ggplot(agta_demo, aes(x=Year)) +
  geom_line(aes(y=Birth_rate), colour = wes_palettes$Darjeeling1[2]) +
  geom_line(aes(y=Death_rate), colour = wes_palettes$Darjeeling1[3]) +
  theme_bw()


demo_sum <- agta_demo %>%
  select(PopSize, Birth_rate, Birth_rate_daily, Death_rate, Death_rate_daily, PopChange_rate, PopChange_rate_daily) %>%
    summarise(across(
    .cols = is.numeric, 
    .fns = list(Mean = mean, SD = sd), na.rm = TRUE, 
    .names = "{col}_{fn}"
    ))
demo_sum 

demo_sum <- as.list(demo_sum)

Agta Band Size

# Import Camp data from Mark Dyble
camps.data <- read_csv("camps.csv")
New names:Rows: 15 Columns: 9── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): camp_name
dbl (8): ...1, camp_total, camp_adult_men, camp_adult_women, camp_all_r, camp_adult_r, forage, turnover
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(camps.data)
# Explore camp size
hist(camps.data$camp_total)


camp.size <- camps.data %>%
  summarise(mean = mean(camp_total),
            sd = sd(camp_total),
            min = min(camp_total),
            max = max(camp_total),
            var = var(camp_total))
camp.size

Single Population Model

Set-up

# Define Paramenters
N <-    sample(camps.data$camp_total, 1)    # Population size
initial_infected <-  1    # Initial infected
simName <- "SEIRS model"       # Simulation name
tf <- 365*3

#Collect parameters
parms <- list(
  beta = 0.6,
  sigma = 0.175,                          # E to I rate
  gamma = 0.2,                           # I to R rate
  omega = 1/180,                         # R to S rate
  mu = demo_sum$Birth_rate_daily_Mean,                            # Birth/death rate per person per day
  alpha = 1/1000) 

#Create the named initial state vector for the U-patch system.

x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

names(x0) <- c("S","E","I", "R", "N")


# Define the state change matrix for a single patch
nu <- matrix(c( -1,  0,  0, +1, +1, -1,  0,  0,  0,  0, # S
                +1, -1,  0,  0,  0,  0, -1,  0,  0,  0, # E
                0, +1, -1,  0,  0,  0,  0, -1,  0, -1, # I
                0,  0, +1, -1,  0,  0,  0,  0, -1,  0, # R 
                0,  0,  0,  0, +1, -1 ,-1, -1, -1, -1), # N
             nrow=5,byrow=TRUE)

# Define propensity functions
a <-c(
        paste0("(beta*I/N)*S"), # Infection
        paste0("sigma*E"),                                       # Becomes infecious
        paste0("gamma*I"),                                       # Recovery from infection
        paste0("omega*R"),       # Loss of immunity
        paste0("mu*N"),                             # Births
        paste0("mu*S"),                                             # Deaths (S)
        paste0("mu*E"),                                             # Deaths (E)
        paste0("mu*I"),                                             # Deaths (I)
        paste0("mu*R"),                                             # Deaths (R)
        paste0("alpha*I")                                           # Deaths from infection
        
      )

Define functions to calculate R0 and expected number of susceptibles at equilibrium, and critical community size (Diekmann et al., 2012).

epsilon^2
[1] 4.610078e-07

Single Population Model

CCS
[1] 4882736
plot_data %>%
  filter(state == "I") %>%
  slice_max(count)
ggsave(filename = "single_plot.pdf", 
       plot = single_plot,
       device = "pdf",
       width = 7, 
       height = 5,
       path = "/Users/matthewhoyle/Github_R_projects/Hunter_Gatherer_models")
```{r}
Error: attempt to use zero-length variable name
# Summary table of endpoint data
sim_output <- sim_output %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output

# Make Summary Table of output
sim_summary <- sim_output %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100, 
            mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/180)
sim_summary

Varying waining immunity

0 Days

#Collect parameters
parms_0 <- parms
parms_0$omega <- 0


# Run simulations with the Direct method
set.seed(4)
out_0 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_0,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_0 <- out_0$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_0 <- ggplot(data = plot_data_0, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_0

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_0 <- list()
sim_list_0 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_0 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_0,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_0 <- out_100_0$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_0[[i]] <- sim_data_0
}

sim_output_0 <- bind_rows(sim_list_0)
# Summary table of endpoint data
sim_output_0 <- sim_output_0 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_0

# Make Summary Table of output
sim_summary_0 <- sim_output_0 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100) %>%
  mutate(omega = 0)
sim_summary_0

1 Days

#Collect parameters
parms_1 <- parms
parms_1$omega <- 1


# Run simulations with the Direct method
set.seed(4)
out_1 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_1,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_1 <- out_1$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_1 <- ggplot(data = plot_data_1, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_1

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_1 <- list()
sim_list_1 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_1 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_1,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_1 <- out_100_1$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_1[[i]] <- sim_data_1
}

sim_output_1 <- bind_rows(sim_list_1)
# Summary table of endpoint data
sim_output_1 <- sim_output_1 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_1

# Make Summary Table of output
sim_summary_1 <- sim_output_1 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1)
sim_summary_1

3 Days

#Collect parameters
parms_3 <- parms
parms_3$omega <- 1/3


# Run simulations with the Direct method
set.seed(4)
out_3 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_3,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_3 <- out_3$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_3 <- ggplot(data = plot_data_3, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_3

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_3 <- list()
sim_list_3 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_3 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_3,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_3 <- out_100_3$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_3[[i]] <- sim_data_3
}

sim_output_3 <- bind_rows(sim_list_3)
# Summary table of endpoint data
sim_output_3 <- sim_output_3 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_3

# Make Summary Table of output
sim_summary_3 <- sim_output_3 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/3)
sim_summary_3

7 Days

#Collect parameters
parms_7 <- parms
parms_7$omega <- 1/7


# Run simulations with the Direct method
set.seed(4)
out_7 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_7,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_7 <- out_7$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_7 <- ggplot(data = plot_data_7, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_7

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_7 <- list()
sim_list_7 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_7 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_7,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_7 <- out_100_7$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_7[[i]] <- sim_data_7
}

sim_output_7 <- bind_rows(sim_list_7)
# Summary table of endpoint data
sim_output_7 <- sim_output_7 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_7

# Make Summary Table of output
sim_summary_7 <- sim_output_7 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/7)
sim_summary_7

10 Days

#Collect parameters
parms_10 <- parms
parms_10$omega <- 1/10


# Run simulations with the Direct method
set.seed(4)
out_10 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_10,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_10 <- out_10$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_10 <- ggplot(data = plot_data_10, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_10

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_10 <- list()
sim_list_10 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_10 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_10,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_10 <- out_100_10$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_10[[i]] <- sim_data_10
}

sim_output_10 <- bind_rows(sim_list_10)
# Summary table of endpoint data
sim_output_10 <- sim_output_10 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_10

# Make Summary Table of output
sim_summary_10 <- sim_output_10 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/10)
sim_summary_10

20 Days

#Collect parameters
parms_20 <- parms
parms_20$omega <- 1/20


# Run simulations with the Direct method
set.seed(4)
out_20 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_20,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_20 <- out_20$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_20 <- ggplot(data = plot_data_20, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_20

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_20 <- list()
sim_list_20 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_20 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_20,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_20 <- out_100_20$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_20[[i]] <- sim_data_20
}

sim_output_20 <- bind_rows(sim_list_20)
# Summary table of endpoint data
sim_output_20 <- sim_output_20 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_20

# Make Summary Table of output
sim_summary_20 <- sim_output_20 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/20)
sim_summary_20

30 Days

#Collect parameters
parms_30 <- parms
parms_30$omega <- 1/30


# Run simulations with the Direct method
set.seed(4)
out_30 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_30,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_30 <- out_30$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_30 <- ggplot(data = plot_data_30, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_30

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_30 <- list()
sim_list_30 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_30 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_30,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_30 <- out_100_30$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_30[[i]] <- sim_data_30
}

sim_output_30 <- bind_rows(sim_list_30)
# Summary table of endpoint data
sim_output_30 <- sim_output_30 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_30

# Make Summary Table of output
sim_summary_30 <- sim_output_30 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/30)
sim_summary_30

40 Days

#Collect parameters
parms_40 <- parms
parms_40$omega <- 1/40


# Run simulations with the Direct method
set.seed(4)
out_40 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_40,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_40 <- out_40$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_40 <- ggplot(data = plot_data_40, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_40

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_40 <- list()
sim_list_40 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_40 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_40,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_40 <- out_100_40$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_40[[i]] <- sim_data_40
}

sim_output_40 <- bind_rows(sim_list_40)
# Summary table of endpoint data
sim_output_40 <- sim_output_40 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_40

# Make Summary Table of output
sim_summary_40 <- sim_output_40 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/40)
sim_summary_40

50 Days

#Collect parameters
parms_50 <- parms
parms_50$omega <- 1/50


# Run simulations with the Direct method
set.seed(4)
out_50 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_50,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_50 <- out_50$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_50 <- ggplot(data = plot_data_50, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_50

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_50 <- list()
sim_list_50 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_50 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_50,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_50 <- out_100_50$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_50[[i]] <- sim_data_50
}

sim_output_50 <- bind_rows(sim_list_50)
# Summary table of endpoint data
sim_output_50 <- sim_output_50 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_50

# Make Summary Table of output
sim_summary_50 <- sim_output_50 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/50)
sim_summary_50

60 Days

#Collect parameters
parms_60 <- parms
parms_60$omega <- 1/60


# Run simulations with the Direct method
set.seed(4)
out_60 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_60,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_60 <- out_60$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_60 <- ggplot(data = plot_data_60, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_60

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_60 <- list()
sim_list_60 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_60 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_60,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_60 <- out_100_60$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_60[[i]] <- sim_data_60
}

sim_output_60 <- bind_rows(sim_list_60)
# Summary table of endpoint data
sim_output_60 <- sim_output_60 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_60

# Make Summary Table of output
sim_summary_60 <- sim_output_60 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/60)
sim_summary_60

70 Days

#Collect parameters
parms_70 <- parms
parms_70$omega <- 1/70


# Run simulations with the Direct method
set.seed(4)
out_70 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_70,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_70 <- out_70$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_70 <- ggplot(data = plot_data_70, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_70

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_70 <- list()
sim_list_70 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_70 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_70,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_70 <- out_100_70$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_70[[i]] <- sim_data_70
}

sim_output_70 <- bind_rows(sim_list_70)
# Summary table of endpoint data
sim_output_70 <- sim_output_70 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_70

# Make Summary Table of output
sim_summary_70 <- sim_output_70 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist)/num_sims)*100,
            mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/70)
sim_summary_70

80 Days

#Collect parameters
parms_80 <- parms
parms_80$omega <- 1/80


# Run simulations with the Direct method
set.seed(4)
out_80 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_80,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_80 <- out_80$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_80 <- ggplot(data = plot_data_80, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_80

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_80 <- list()
sim_list_80 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_80 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_80,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_80 <- out_100_80$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_80[[i]] <- sim_data_80
}

sim_output_80 <- bind_rows(sim_list_80)
# Summary table of endpoint data
sim_output_80 <- sim_output_80 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_80

# Make Summary Table of output
sim_summary_80 <- sim_output_80 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/80)
sim_summary_80

100 Days

150 Days

#Collect parameters
parms_150 <- parms
parms_150$omega <- 1/150


# Run simulations with the Direct method
set.seed(4)
out_150 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_150,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_150 <- out_150$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_150 <- ggplot(data = plot_data_150, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_150

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_150 <- list()
sim_list_150 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_150 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_150,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_150 <- out_100_150$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_150[[i]] <- sim_data_150
}

sim_output_150 <- bind_rows(sim_list_150)
# Summary table of endpoint data
sim_output_150 <- sim_output_150 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_150

# Make Summary Table of output
sim_summary_150 <- sim_output_150 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/150)
sim_summary_150

365 Days

#Collect parameters
parms_365 <- parms
parms_365$omega <- 1/365


# Run simulations with the Direct method
set.seed(4)
out_365 <- ssa(
  x0 = x0,
  a = a,
  nu = nu,
  parms = parms_365,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_365 <- out_365$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "state", values_to = "count") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_365 <- ggplot(data = plot_data_365, aes(x=t, y=count, colour=state))+
  geom_line()+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_365

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_365 <- list()
sim_list_365 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  N <-     sample(camps.data$camp_total, 1)    # Sample different patch sizes for each sim
  
  x0 <- c(N - initial_infected, initial_infected, 0, 0, N)

  names(x0) <- c("S","E","I", "R", "N")


  out_100_365 <- ssa(
    x0 = x0,
    a = a,
    nu = nu,
    parms = parms_365,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_365 <- out_100_365$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "state", values_to = "count") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, I, N, persist)
  
  sim_list_365[[i]] <- sim_data_365
}

sim_output_365 <- bind_rows(sim_list_365)
# Summary table of endpoint data
sim_output_365 <- sim_output_365 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_365

# Make Summary Table of output
sim_summary_365 <- sim_output_365 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/365)
sim_summary_365

Results

waning_results_single <- sim_summary %>%
  bind_rows(sim_summary_1) %>%
  bind_rows(sim_summary_3) %>%
  bind_rows(sim_summary_7) %>%
  bind_rows(sim_summary_10) %>%
  bind_rows(sim_summary_20) %>%
  bind_rows(sim_summary_30) %>%
  bind_rows(sim_summary_40) %>%
  bind_rows(sim_summary_50) %>%
  bind_rows(sim_summary_60) %>%
  bind_rows(sim_summary_70) %>%
  bind_rows(sim_summary_80) %>%
  bind_rows(sim_summary_100) %>%
  bind_rows(sim_summary_150) %>%
  bind_rows(sim_summary_365) %>%
  mutate(immunity_duration = 1/omega) %>%
  arrange(immunity_duration) %>%
  mutate(model="single")

write_csv(waning_results_single, file = "/Users/matthewhoyle/Github_R_projects/Hunter_Gatherer_models/waning_results_single.csv")

waning_results_single
NA
ggplot(waning_results_single, aes(immunity_duration, sum_persist)) +
  geom_line()+
  geom_point()+
  theme_bw()

Metapopulation Model

###Set-up

# Define Paramenters
patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Patch size
U <- length(patchPopSize)                    # Number of patches
initial_infected <-  as.vector(rmultinom(1, 1, rep(0.5, U)))   # Initial infected (initial infected patch randomly generated)
initial_infected_patch <- which(initial_infected > 0)
simName <- "SIRS metapopulation model"       # Simulation name
tf <- 365*3                                   # Final time

# Agta Hunter-Gatherer contact rates
within_pop_contact = 1
between_pop_contact = 0.5/U     # normalised by number of patches 

#Create the named initial state vector for the U-patch system.

x0_meta <- unlist(lapply(
  seq_len(U), 
  function(i){ 
    c(patchPopSize[i] - initial_infected[i], initial_infected[i], 0, 0, patchPopSize[i])
  }
))

names(x0_meta) <- unlist(lapply(seq_len(U), function(i) paste0(c("S","E","I", "R", "N"), i)))


# Define the state change matrix for a single patch
nu_meta <- matrix(c( -1,  0,  0, +1, +1, -1,  0,  0,  0,  0, # S
                     +1, -1,  0,  0,  0,  0, -1,  0,  0,  0, # E
                      0, +1, -1,  0,  0,  0,  0, -1,  0, -1, # I
                      0,  0, +1, -1,  0,  0,  0,  0, -1,  0, # R 
                      0,  0,  0,  0, +1, -1 ,-1, -1, -1, -1), # N
             nrow=5,byrow=TRUE)

# Define propensity functions
# Mass-action
a_meta <-
  unlist(lapply(
    seq_len(U),
    function(patch) {
      i <- patch
      patches <- 1:U
      #j <- if (patch == 1) U else patch - 1
      other_patches <- patches[-i]
      patch_beta <- c()
      for(k in (1:(U-1))){
        patch_beta[k] = paste0("+(beta_", other_patches[k],i, "*I", other_patches[k], "/N", other_patches[k], ")*S", i)
      }
      c(
        paste0("(beta_", i, i, "*I", i,"/N", i, ")*S",i, paste0(patch_beta, collapse="")), # Infection
        paste0("sigma*E", i),                                       # Becomes infecious
        paste0("gamma*I", i),                                       # Recovery from infection
        paste0("omega*R", i),       # Loss of immunity
        paste0("mu*N", i),                             # Births
        paste0("mu*S", i),                                             # Deaths (S)
        paste0("mu*E", i),                                             # Deaths (E)
        paste0("mu*I", i),                                             # Deaths (I)
        paste0("mu*R", i),                                             # Deaths (R)
        paste0("alpha*I", i)                                           # Deaths from infection
        
      )
    }
  ))

Define functions for calculating R0 from next-generation matrix

# Calculate R0 from NGM

R0ngm <- function(nextgen_matrix) {
  eigenvalues = eigen(nextgen_matrix, only.values = T)
  R0 = max(abs(eigenvalues$values))
  return(R0)
}

beta.ngm <- function(beta_matrix) {
  eigenvalues = eigen(beta_matrix, only.values = T)
  beta_ngm = max(abs(eigenvalues$values))
  return(beta_ngm)
}

Metapopulation Model

#Collect parameters
parms_meta <- list(
  sigma = 0.175,                          # E to I rate
  gamma = 0.2,                           # I to R rate
  omega = 1/180,                         # R to S rate
  mu = demo_sum$Birth_rate_daily_Mean,                            # Birth/death rate per person per day
  alpha = 1/1000) 

# Define transmission terms and populate next-generation matrix
beta <- 0.6

nextgen_matrix <- matrix(nrow = U, ncol = U, data = 0)
beta_matrix <- matrix(nrow = U, ncol = U, data = 0)


for(i in 1:U){
  for(j in 1:U){
    parms_meta[[paste0("beta_",i,i)]] = within_pop_contact*beta
    nextgen_matrix[i,i] = within_pop_contact*beta*(1/parms_meta$gamma)
    parms_meta[[paste0("beta_",j,i)]] = between_pop_contact*beta
    nextgen_matrix[j,i] = between_pop_contact*beta*(1/parms_meta$gamma)
    nextgen_matrix[i,j] = between_pop_contact*beta*(1/parms_meta$gamma)
    parms_meta[[paste0("beta_",j,j)]] = within_pop_contact*beta
    nextgen_matrix[j,j] = within_pop_contact*beta*(1/parms_meta$gamma)
    beta_matrix[i,i] = within_pop_contact*beta
    beta_matrix[j,i] = between_pop_contact*beta
    beta_matrix[i,j] = between_pop_contact*beta
    beta_matrix[j,j] = within_pop_contact*beta
  }
  parms_meta[[paste0("N", i)]] = patchPopSize[i]
}
# Run simulations with the Direct method
set.seed(4)
out_meta <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Plot
plot_data_meta <- out_meta$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta <- ggplot(data = plot_data_meta, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 1, scales = "free_y")+
  labs(x="Time (Days)",
       y="Number of Individuals",
       colour="State")+
  theme_bw()
plot_meta

ggsave(filename = "meta_plot.pdf", 
       plot = plot_meta,
       device = "pdf",
       width = 7, 
       height = 8,
       path = "/Users/matthewhoyle/Github_R_projects/Hunter_Gatherer_models")

## Table showing extinction/transmission info for each patch

extinct_data_meta <- out_meta$data %>%
  as_tibble() %>%
  slice_max(t) %>%
  distinct() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N")),
         persist = case_when(state=="I" & count > 0 ~ T, 
                             state=="I" & count == 0 ~ F)) %>%
  drop_na() %>%
  select(patch, count, persist)
extinct_data_meta
beta_meta <- beta.ngm(beta_matrix)
paste0("Beta for whole system = ", beta_meta)
[1] "Beta for whole system = 0.857142857142857"
R0_meta <- R0ngm(nextgen_matrix)
paste0("R0 = ", R0_meta)
[1] "R0 = 4.28571428571429"
paste0("Actual number of infecteds at end of sim = ", sum(extinct_data_meta$count))
[1] "Actual number of infecteds at end of sim = 0"
 # Total number of infecteds at the end of sim across all patches

sim_endpoint_meta <- as_tibble(out_meta$data) %>%
  slice_max(t) %>%
  distinct()


paste0("Did simulation run reach final endpoint?")
[1] "Did simulation run reach final endpoint?"
if (sim_endpoint_meta$t >= tf) {
  print("Yes")
} else {
  print("No")}
[1] "Yes"
## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta <- list()
sim_list_meta <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(lapply(
  seq_len(U), 
  function(x){ 
    c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
  }
))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))
  
  out_100_meta <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta <- out_100_meta$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta[[i]] <- sim_data_meta
}

sim_output_meta <- bind_rows(sim_list_meta)
# Summary table of endpoint data
sim_output_meta <- sim_output_meta %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta
# Make Summary Table of output
sim_summary_meta <- sim_output_meta %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,
            mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/180)
sim_summary_meta

Varying waining immunity

0 Days

#Collect parameters
parms_meta_0 <- parms_meta
parms_meta_0$omega <- 0


# Run simulations with the Direct method
set.seed(4)
out_meta_0 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_0,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_0 <- out_meta_0$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_0 <- ggplot(data = plot_data_meta_0, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_0

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_0 <- list()
sim_list_meta_0 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_0 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_0,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_0 <- out_100_meta_0$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_0[[i]] <- sim_data_meta_0
}

sim_output_meta_0 <- bind_rows(sim_list_meta_0)
# Summary table of endpoint data
sim_output_meta_0 <- sim_output_meta_0 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_0

# Make Summary Table of output
sim_summary_meta_0 <- sim_output_meta_0 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,
            mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 0)
sim_summary_meta_0

1 Day

#Collect parameters
parms_meta_1 <- parms_meta
parms_meta_1$omega <- 1


# Run simulations with the Direct method
set.seed(4)
out_meta_1 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_1,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_1 <- out_meta_1$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_1 <- ggplot(data = plot_data_meta_1, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_1

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_1 <- list()
sim_list_meta_1 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_1 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_1,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_1 <- out_100_meta_1$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_1[[i]] <- sim_data_meta_1
}

sim_output_meta_1 <- bind_rows(sim_list_meta_1)
# Summary table of endpoint data
sim_output_meta_1 <- sim_output_meta_1 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_1

# Make Summary Table of output
sim_summary_meta_1 <- sim_output_meta_1 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1)
sim_summary_meta_1

3 Days

#Collect parameters
parms_meta_3 <- parms_meta
parms_meta_3$omega <- 1/3


# Run simulations with the Direct method
set.seed(4)
out_meta_3 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_3,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_3 <- out_meta_3$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_3 <- ggplot(data = plot_data_meta_3, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_3

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_3 <- list()
sim_list_meta_3 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_3 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_3,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_3 <- out_100_meta_3$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_3[[i]] <- sim_data_meta_3
}

sim_output_meta_3 <- bind_rows(sim_list_meta_3)
# Summary table of endpoint data
sim_output_meta_3 <- sim_output_meta_3 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_3

# Make Summary Table of output
sim_summary_meta_3 <- sim_output_meta_3 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/3)
sim_summary_meta_3

7 Days

#Collect parameters
parms_meta_7 <- parms_meta
parms_meta_7$omega <- 1/7


# Run simulations with the Direct method
set.seed(4)
out_meta_7 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_7,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_7 <- out_meta_7$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_7 <- ggplot(data = plot_data_meta_7, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_7

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_7 <- list()
sim_list_meta_7 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_7 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_7,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_7 <- out_100_meta_7$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_7[[i]] <- sim_data_meta_7
}

sim_output_meta_7 <- bind_rows(sim_list_meta_7)
# Summary table of endpoint data
sim_output_meta_7 <- sim_output_meta_7 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_7

# Make Summary Table of output
sim_summary_meta_7 <- sim_output_meta_7 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/7)
sim_summary_meta_7

10 Days

#Collect parameters
parms_meta_10 <- parms_meta
parms_meta_10$omega <- 1/10

# Run simulations with the Direct method
set.seed(4)
out_meta_10 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_10,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_10 <- out_meta_10$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_10 <- ggplot(data = plot_data_meta_10, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_10

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_10 <- list()
sim_list_meta_10 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_10 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_10,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_10 <- out_100_meta_10$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_10[[i]] <- sim_data_meta_10
}

sim_output_meta_10 <- bind_rows(sim_list_meta_10)
# Summary table of endpoint data
sim_output_meta_10 <- sim_output_meta_10 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))

# Make Summary Table of output
sim_summary_meta_10 <- sim_output_meta_10 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/14)
sim_summary_meta_10

20 Days

#Collect parameters
parms_meta_20 <- parms_meta
parms_meta_20$omega <- 1/20


# Run simulations with the Direct method
set.seed(4)
out_meta_20 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_20,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_20 <- out_meta_20$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_20 <- ggplot(data = plot_data_meta_20, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_20

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_20 <- list()
sim_list_meta_20 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_20 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_20,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_20 <- out_100_meta_20$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_20[[i]] <- sim_data_meta_20
}

sim_output_meta_20 <- bind_rows(sim_list_meta_20)
# Summary table of endpoint data
sim_output_meta_20 <- sim_output_meta_20 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_20

# Make Summary Table of output
sim_summary_meta_20 <- sim_output_meta_20 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/20)
sim_summary_meta_20

30 Days

#Collect parameters
parms_meta_30 <- parms_meta
parms_meta_30$omega <- 1/30


# Run simulations with the Direct method
set.seed(4)
out_meta_30 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_30,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_30 <- out_meta_30$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_30 <- ggplot(data = plot_data_meta_30, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_30

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_30 <- list()
sim_list_meta_30 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_30 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_30,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_30 <- out_100_meta_30$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_30[[i]] <- sim_data_meta_30
}

sim_output_meta_30 <- bind_rows(sim_list_meta_30)
# Summary table of endpoint data
sim_output_meta_30 <- sim_output_meta_30 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_30

# Make Summary Table of output
sim_summary_meta_30 <- sim_output_meta_30 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,
            mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/30)
sim_summary_meta_30

40 Days

#Collect parameters
parms_meta_40 <- parms_meta
parms_meta_40$omega <- 1/40


# Run simulations with the Direct method
set.seed(4)
out_meta_40 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_40,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_40 <- out_meta_40$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_40 <- ggplot(data = plot_data_meta_40, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_40

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_40 <- list()
sim_list_meta_40 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_40 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_40,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_40 <- out_100_meta_40$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_40[[i]] <- sim_data_meta_40
}

sim_output_meta_40 <- bind_rows(sim_list_meta_40)
# Summary table of endpoint data
sim_output_meta_40 <- sim_output_meta_40 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_40

# Make Summary Table of output
sim_summary_meta_40 <- sim_output_meta_40 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/40)
sim_summary_meta_40

50 Days

#Collect parameters
parms_meta_50 <- parms_meta
parms_meta_50$omega <- 1/50


# Run simulations with the Direct method
set.seed(4)
out_meta_50 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_50,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_50 <- out_meta_50$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_50 <- ggplot(data = plot_data_meta_50, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_50

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_50 <- list()
sim_list_meta_50 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_50 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_50,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_50 <- out_100_meta_50$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_50[[i]] <- sim_data_meta_50
}

sim_output_meta_50 <- bind_rows(sim_list_meta_50)
# Summary table of endpoint data
sim_output_meta_50 <- sim_output_meta_50 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_50

# Make Summary Table of output
sim_summary_meta_50 <- sim_output_meta_50 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/50)
sim_summary_meta_50

60 Days

#Collect parameters
parms_meta_60 <- parms_meta
parms_meta_60$omega <- 1/60


# Run simulations with the Direct method
set.seed(4)
out_meta_60 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_60,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_60 <- out_meta_60$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_60 <- ggplot(data = plot_data_meta_60, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_60

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_60 <- list()
sim_list_meta_60 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_60 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_60,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_60 <- out_100_meta_60$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_60[[i]] <- sim_data_meta_60
}

sim_output_meta_60 <- bind_rows(sim_list_meta_60)
# Summary table of endpoint data
sim_output_meta_60 <- sim_output_meta_60 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_60

# Make Summary Table of output
sim_summary_meta_60 <- sim_output_meta_60 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/60)
sim_summary_meta_60

70 Days

#Collect parameters
parms_meta_70 <- parms_meta
parms_meta_70$omega <- 1/70


# Run simulations with the Direct method
set.seed(4)
out_meta_70 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_70,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_70 <- out_meta_70$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_70 <- ggplot(data = plot_data_meta_70, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_70

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_70 <- list()
sim_list_meta_70 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_70 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_70,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_70 <- out_100_meta_70$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_70[[i]] <- sim_data_meta_70
}

sim_output_meta_70 <- bind_rows(sim_list_meta_70)
# Summary table of endpoint data
sim_output_meta_70 <- sim_output_meta_70 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_70

# Make Summary Table of output
sim_summary_meta_70 <- sim_output_meta_70 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/70)
sim_summary_meta_70

80 Days

#Collect parameters
parms_meta_80 <- parms_meta
parms_meta_80$omega <- 1/80


# Run simulations with the Direct method
set.seed(4)
out_meta_80 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_80,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_80 <- out_meta_80$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_80 <- ggplot(data = plot_data_meta_80, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_80

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_80 <- list()
sim_list_meta_80 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_80 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_80,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_80 <- out_100_meta_80$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_80[[i]] <- sim_data_meta_80
}

sim_output_meta_80 <- bind_rows(sim_list_meta_80)
# Summary table of endpoint data
sim_output_meta_80 <- sim_output_meta_80 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_80

# Make Summary Table of output
sim_summary_meta_80 <- sim_output_meta_80 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/80)
sim_summary_meta_80

90 Days

#Collect parameters
parms_meta_90 <- parms_meta
parms_meta_90$omega <- 1/90


# Run simulations with the Direct method
set.seed(4)
out_meta_90 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_90,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_90 <- out_meta_90$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_90 <- ggplot(data = plot_data_meta_90, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_90

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_90 <- list()
sim_list_meta_90 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_90 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_90,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_90 <- out_100_meta_90$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_90[[i]] <- sim_data_meta_90
}

sim_output_meta_90 <- bind_rows(sim_list_meta_90)
# Summary table of endpoint data
sim_output_meta_90 <- sim_output_meta_90 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_90

# Make Summary Table of output
sim_summary_meta_90 <- sim_output_meta_90 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/90)
sim_summary_meta_90

100 Days

#Collect parameters
parms_meta_100 <- parms_meta
parms_meta_100$omega <- 1/100


# Run simulations with the Direct method
set.seed(4)
out_meta_100 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_100,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_100 <- out_meta_100$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_100 <- ggplot(data = plot_data_meta_100, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_100

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_100 <- list()
sim_list_meta_100 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_100 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_100,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_100 <- out_100_meta_100$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_100[[i]] <- sim_data_meta_100
}

sim_output_meta_100 <- bind_rows(sim_list_meta_100)
# Summary table of endpoint data
sim_output_meta_100 <- sim_output_meta_100 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_100

# Make Summary Table of output
sim_summary_meta_100 <- sim_output_meta_100 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/100)
sim_summary_meta_100

110 Days

#Collect parameters
parms_meta_110 <- parms_meta
parms_meta_110$omega <- 1/110


# Run simulations with the Direct method
set.seed(4)
out_meta_110 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_110,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_110 <- out_meta_110$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_110 <- ggplot(data = plot_data_meta_110, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_110

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_110 <- list()
sim_list_meta_110 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_110 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_110,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_110 <- out_100_meta_110$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_110[[i]] <- sim_data_meta_110
}

sim_output_meta_110 <- bind_rows(sim_list_meta_110)
# Summary table of endpoint data
sim_output_meta_110 <- sim_output_meta_110 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_110

# Make Summary Table of output
sim_summary_meta_110 <- sim_output_meta_110 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/110)
sim_summary_meta_110

120 Days

#Collect parameters
parms_meta_120 <- parms_meta
parms_meta_120$omega <- 1/120


# Run simulations with the Direct method
set.seed(4)
out_meta_120 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_120,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_120 <- out_meta_120$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_120 <- ggplot(data = plot_data_meta_120, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_120

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_120 <- list()
sim_list_meta_120 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_120 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_120,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_120 <- out_100_meta_120$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_120[[i]] <- sim_data_meta_120
}

sim_output_meta_120 <- bind_rows(sim_list_meta_120)
# Summary table of endpoint data
sim_output_meta_120 <- sim_output_meta_120 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_120

# Make Summary Table of output
sim_summary_meta_120 <- sim_output_meta_120 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/120)
sim_summary_meta_120

130 Days

#Collect parameters
parms_meta_130 <- parms_meta
parms_meta_130$omega <- 1/130


# Run simulations with the Direct method
set.seed(4)
out_meta_130 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_130,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_130 <- out_meta_130$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_130 <- ggplot(data = plot_data_meta_130, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_130

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_130 <- list()
sim_list_meta_130 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_130 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_130,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_130 <- out_100_meta_130$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_130[[i]] <- sim_data_meta_130
}

sim_output_meta_130 <- bind_rows(sim_list_meta_130)
# Summary table of endpoint data
sim_output_meta_130 <- sim_output_meta_130 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_130

# Make Summary Table of output
sim_summary_meta_130 <- sim_output_meta_130 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/130)
sim_summary_meta_130

150 Days

#Collect parameters
parms_meta_150 <- parms_meta
parms_meta_150$omega <- 1/150


# Run simulations with the Direct method
set.seed(4)
out_meta_150 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_150,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_150 <- out_meta_150$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_150 <- ggplot(data = plot_data_meta_150, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_150

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_150 <- list()
sim_list_meta_150 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_150 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_150,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_150 <- out_100_meta_150$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_150[[i]] <- sim_data_meta_150
}

sim_output_meta_150 <- bind_rows(sim_list_meta_150)
# Summary table of endpoint data
sim_output_meta_150 <- sim_output_meta_150 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_150

# Make Summary Table of output
sim_summary_meta_150 <- sim_output_meta_150 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/150)
sim_summary_meta_150

220 Days

#Collect parameters
parms_meta_220 <- parms_meta
parms_meta_220$omega <- 1/220


# Run simulations with the Direct method
set.seed(4)
out_meta_220 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_220,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_220 <- out_meta_220$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_220 <- ggplot(data = plot_data_meta_220, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_220

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_220 <- list()
sim_list_meta_220 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_220 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_220,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_220 <- out_100_meta_220$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_220[[i]] <- sim_data_meta_220
}

sim_output_meta_220 <- bind_rows(sim_list_meta_220)
# Summary table of endpoint data
sim_output_meta_220 <- sim_output_meta_220 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_220

# Make Summary Table of output
sim_summary_meta_220 <- sim_output_meta_220 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/220)
sim_summary_meta_220

270 Days

#Collect parameters
parms_meta_270 <- parms_meta
parms_meta_270$omega <- 1/270


# Run simulations with the Direct method
set.seed(4)
out_meta_270 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_270,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_270 <- out_meta_270$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_270 <- ggplot(data = plot_data_meta_270, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_270

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_270 <- list()
sim_list_meta_270 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_270 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_270,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_270 <- out_100_meta_270$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_270[[i]] <- sim_data_meta_270
}

sim_output_meta_270 <- bind_rows(sim_list_meta_270)
# Summary table of endpoint data
sim_output_meta_270 <- sim_output_meta_270 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_270

# Make Summary Table of output
sim_summary_meta_270 <- sim_output_meta_270 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/270)
sim_summary_meta_270

365 Days

#Collect parameters
parms_meta_365 <- parms_meta
parms_meta_365$omega <- 1/365


# Run simulations with the Direct method
set.seed(4)
out_meta_365 <- ssa(
  x0 = x0_meta,
  a = a_meta,
  nu = nu_meta,
  parms = parms_meta_365,
  tf = tf,
  method = ssa.d(),
  simName = simName,
  verbose = FALSE,
  consoleInterval = 1
)


## Extra Plots
plot_data_meta_365 <- out_meta_365$data %>%
  as_tibble() %>%
  pivot_longer(!t, names_to = "ID", values_to = "count") %>%
  separate(ID, 
           into = c("state", "patch"), 
           sep = "(?<=[A-Za-z])(?=[0-9])") %>%
  mutate(state = factor(state, levels = c("S", "E", "I", "R", "N"))) #%>%
  #filter(state != "N")

plot_meta_365 <- ggplot(data = plot_data_meta_365, aes(x=t, y=count, colour=state))+
  geom_line()+
  facet_wrap(~factor(patch, levels = unique(patch)) ,ncol = 3, scales = "free_y")+
  labs(x="Time",
       y="Frequency")+
  theme_bw()
plot_meta_365

## Run multiple simulations and saving output
num_sims <- 1000
sim_list_meta_365 <- list()
sim_list_meta_365 <- vector("list", length = num_sims)

for (i in 1:num_sims){
  set.seed(i)
  
  patchPopSize <-     sample(camps.data$camp_total, 7, replace = TRUE)    # Sample different patch sizes for each sim
  x0_meta <- unlist(
      lapply(
        seq_len(U),
        function(x){
          c(patchPopSize[x] - initial_infected[x], initial_infected[x], 0, 0, patchPopSize[x])
          }
        ))

names(x0_meta) <- unlist(lapply(seq_len(U), function(x) paste0(c("S","E","I", "R", "N"), x)))

  out_100_meta_365 <- ssa(
    x0 = x0_meta,
    a = a_meta,
    nu = nu_meta,
    parms = parms_meta_365,
    tf = tf,
    method = ssa.d(),
    simName = simName,
    verbose = FALSE,
    consoleInterval = 1
  )

  
# Extract Final time point from output data
  sim_data_meta_365 <- out_100_meta_365$data %>%
    as_tibble() %>%
    slice_max(t) %>%
    distinct() %>%
    pivot_longer(!t, names_to = "ID", values_to = "count") %>%
    separate(ID, 
             into = c("state", "patch"), 
             sep = "(?<=[A-Za-z])(?=[0-9])") %>%
    pivot_wider(names_from = state, values_from = count) %>%
    mutate(persist = case_when(I > 0 ~ T, 
                               I == 0 ~ F),
           sim = i) %>%
    select(sim, patch, I, N, persist)
  
  sim_list_meta_365[[i]] <- sim_data_meta_365
}

sim_output_meta_365 <- bind_rows(sim_list_meta_365)
# Summary table of endpoint data
sim_output_meta_365 <- sim_output_meta_365 %>%
  group_by(sim) %>%
  summarise(total_I = sum(I), 
            total_N = sum(N)) %>%
  mutate(percent_persist = total_I/(total_N)*100,
         persist = case_when(total_I > 0 ~ T, 
                               total_I == 0 ~ F))
sim_output_meta_365

# Make Summary Table of output
sim_summary_meta_365 <- sim_output_meta_365 %>%
  summarise(mean_infecteds = mean(total_I),
            sum_persist = (sum(persist, na.rm = T)/num_sims)*100,              mean_percent_infected = mean(percent_persist)) %>%
  mutate(omega = 1/365)
sim_summary_meta_365

Single

Results

waning_results <- sim_summary_meta %>%
  bind_rows(sim_summary_meta_3) %>%
  bind_rows(sim_summary_meta_7) %>%
  bind_rows(sim_summary_meta_10) %>%
  bind_rows(sim_summary_meta_20) %>%
  bind_rows(sim_summary_meta_30) %>%
  bind_rows(sim_summary_meta_40) %>%
  bind_rows(sim_summary_meta_50) %>%
  bind_rows(sim_summary_meta_60) %>%
  bind_rows(sim_summary_meta_70) %>%
  bind_rows(sim_summary_meta_80) %>%
  bind_rows(sim_summary_meta_90) %>%
  bind_rows(sim_summary_meta_100) %>%
  bind_rows(sim_summary_meta_110) %>%
  bind_rows(sim_summary_meta_120) %>%
  bind_rows(sim_summary_meta_130) %>%
  bind_rows(sim_summary_meta_150) %>%
  bind_rows(sim_summary_meta_220) %>%
  bind_rows(sim_summary_meta_270) %>%
  bind_rows(sim_summary_meta_365) %>%
  mutate(immunity_duration = 1/omega) %>%
  arrange(immunity_duration) %>%
  mutate(model = "meta")

write_csv(waning_results, file = "/Users/matthewhoyle/Github_R_projects/Hunter_Gatherer_models/waning_results.csv")

waning_results
NA
ggplot(waning_results, aes(immunity_duration, sum_persist)) +
  geom_line()+
  geom_point()+
  theme_bw()

Combined Results

combined_waning <- waning_results %>%
  bind_rows(waning_results_single)

combined_waning

write_csv(combined_waning, file = "/Users/matthewhoyle/Github_R_projects/Hunter_Gatherer_models/combined_waning_results.csv")
combined_plot <- ggplot(combined_waning, aes(immunity_duration, sum_persist, colour = model))+
  geom_line()+
  geom_point()+
  geom_segment(x = -Inf, y = 50, xend = 91.5, yend = 50, linetype = "dashed", colour = "grey") +
  geom_segment(x = 5, y = 50, xend = 5, yend = -Inf, linetype = "dashed", colour = "grey") +
  geom_segment(x = 91.5, y = 50, xend = 91.5, yend = -Inf, linetype = "dashed", colour = "grey") +
  labs(x = "Duration of immunity",
       y = "Probability of persistence after 3 years (%)", 
       colour = "Model Type")+
  scale_color_discrete(type = wes_palette("Darjeeling1", type = "discrete")[1:2],
                       labels = c("Metapopulation", "Single Population"))+
  theme_bw()

combined_plot

ggsave(filename = "combined_plot.pdf", 
       plot = combined_plot,
       device = "pdf",
       width = 7, 
       height = 5,
       path = "/Users/matthewhoyle/Github_R_projects/Hunter_Gatherer_models")

LS0tCnRpdGxlOiAiTW9kZWxsaW5nIHRoZSBwZXJzaXN0ZW5jZSBvZiBpbmZlY3Rpb3VzIGRpc2Vhc2VzIGluIHByZS1hZ3JpY3VsdHVyYWwgSHVudGVyLWdhdGhlcmVycyIKc3VidGl0bGU6ICJDb25kZW5zZWQgUmVwb3J0IgphdXRob3I6ICJNYXR0aGV3IEhveWxlIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCiMjIFNldC11cApgYGB7cn0KIyBybShsaXN0ID0gbHMoKSkKbGlicmFyeShkcGx5cikKbGlicmFyeSh3ZXNhbmRlcnNvbikKbGlicmFyeShHaWxsZXNwaWVTU0EpCmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCiMjIE1vZGVsIFBhcmFtZXRlciBlc3RpbWF0aW9uCgojIyMgQWd0YSBIdW50ZXItR2F0aGVyZXIgRGVtb2dyYXBoeQoKSW5mb3JtYXRpb24gcmVnYXJkaW5nIGJpcnRocywgZGVhdGhzIGFuZCBwb3B1bGF0aW9uIHNpemUgd2VyZSBvYnRhaW4gZnJvbSBhIHN0dWR5IGNvbmR1Y3RlZCBieSBIZWFkbGFuZCBldCBhbC4sICgyMDExKS4gQXV0aG9ycyBjb25kdWN0ZWQgYSBjZW5zdXMtbGlrZSBzdXJ2ZXkgb2YgdGhlIApgYGB7cn0KYWd0YV9kZW1vIDwtIHJlYWQuY3N2KCJBZ3RhUG9wRHluYW1pY3NfSGVhZGxhbmQyMDA3LmNzdiIpCgpnZ3Bsb3QoYWd0YV9kZW1vLCBhZXMoeD1ZZWFyKSkgKwogIGdlb21fbGluZShhZXMoeT1Qb3BTaXplKSwgY29sb3VyID0gd2VzX3BhbGV0dGVzJERhcmplZWxpbmcxWzFdKSArCiAgZ2VvbV9saW5lKGFlcyh5PUJpcnRocyksIGNvbG91ciA9IHdlc19wYWxldHRlcyREYXJqZWVsaW5nMVsyXSkgKwogIGdlb21fbGluZShhZXMoeT1EZWF0aHMpLCBjb2xvdXIgPSB3ZXNfcGFsZXR0ZXMkRGFyamVlbGluZzFbM10pICsKICB0aGVtZV9idygpCmBgYAoKIyMjIyBQb3B1bGF0aW9uIFNpemUKYGBge3J9Cmhpc3QoYWd0YV9kZW1vJFBvcFNpemUpCnN1bW1hcnkoYWd0YV9kZW1vJFBvcFNpemUpCmBgYAoKIyMjIyBCaXJ0aHMKYGBge3J9Cmhpc3QoYWd0YV9kZW1vJEJpcnRocykKc3VtbWFyeShhZ3RhX2RlbW8kQmlydGhzKQpgYGAKCiMjIyMgRGVhdGhzCmBgYHtyfQpoaXN0KGFndGFfZGVtbyREZWF0aHMpCnN1bW1hcnkoYWd0YV9kZW1vJERlYXRocykKYGBgCgojIyMjIEJpcnRoL0RlYXRoIHJhdGUgcGVyIHBlcnNvbiBwZXIgZGF5CmBgYHtyIHdhcm5pbmc9RkFMU0V9CmFndGFfZGVtbyA8LSBhZ3RhX2RlbW8gJT4lCiAgbXV0YXRlKEJpcnRoX3JhdGUgPSBCaXJ0aHMvKEZlbWFsZSoyKSwKICAgICAgICAgQmlydGhfcmF0ZV9kYWlseSA9ICgxICsgQmlydGhfcmF0ZSkgXiAoMS8zNjUpIC0gMSwKICAgICAgICAgRGVhdGhfcmF0ZSA9IChEZWF0aHMvUG9wU2l6ZSksCiAgICAgICAgIERlYXRoX3JhdGVfZGFpbHkgPSAoMSArIERlYXRoX3JhdGUpIF4gKDEvMzY1KSAtIDEsCiAgICAgICAgIFBvcENoYW5nZSA9IChkaWZmID0gUG9wU2l6ZSAtIGxhZyhQb3BTaXplLCBkZWZhdWx0ID0gZmlyc3QoUG9wU2l6ZSkpKSwKICAgICAgICAgUG9wQ2hhbmdlX3JhdGUgPSBhYnMoUG9wQ2hhbmdlKS9Qb3BTaXplLAogICAgICAgICBQb3BDaGFuZ2VfcmF0ZV9kYWlseSA9ICgxICsgUG9wQ2hhbmdlX3JhdGUpIF4gKDEvMzY1KSAtIDEpCmhlYWQoYWd0YV9kZW1vKQoKCmhpc3QoYWd0YV9kZW1vJEJpcnRoX3JhdGUpCmhpc3QoYWd0YV9kZW1vJERlYXRoX3JhdGUpCgpnZ3Bsb3QoYWd0YV9kZW1vLCBhZXMoeD1ZZWFyKSkgKwogIGdlb21fbGluZShhZXMoeT1CaXJ0aF9yYXRlKSwgY29sb3VyID0gd2VzX3BhbGV0dGVzJERhcmplZWxpbmcxWzJdKSArCiAgZ2VvbV9saW5lKGFlcyh5PURlYXRoX3JhdGUpLCBjb2xvdXIgPSB3ZXNfcGFsZXR0ZXMkRGFyamVlbGluZzFbM10pICsKICB0aGVtZV9idygpCgpkZW1vX3N1bSA8LSBhZ3RhX2RlbW8gJT4lCiAgc2VsZWN0KFBvcFNpemUsIEJpcnRoX3JhdGUsIEJpcnRoX3JhdGVfZGFpbHksIERlYXRoX3JhdGUsIERlYXRoX3JhdGVfZGFpbHksIFBvcENoYW5nZV9yYXRlLCBQb3BDaGFuZ2VfcmF0ZV9kYWlseSkgJT4lCiAgICBzdW1tYXJpc2UoYWNyb3NzKAogICAgLmNvbHMgPSBpcy5udW1lcmljLCAKICAgIC5mbnMgPSBsaXN0KE1lYW4gPSBtZWFuLCBTRCA9IHNkKSwgbmEucm0gPSBUUlVFLCAKICAgIC5uYW1lcyA9ICJ7Y29sfV97Zm59IgogICAgKSkKZGVtb19zdW0gCgpkZW1vX3N1bSA8LSBhcy5saXN0KGRlbW9fc3VtKQpgYGAKCiMjIyBBZ3RhIEJhbmQgU2l6ZQpgYGB7cn0KIyBJbXBvcnQgQ2FtcCBkYXRhIGZyb20gTWFyayBEeWJsZQpjYW1wcy5kYXRhIDwtIHJlYWRfY3N2KCJjYW1wcy5jc3YiKQoKaGVhZChjYW1wcy5kYXRhKQpgYGAKCgpgYGB7cn0KIyBFeHBsb3JlIGNhbXAgc2l6ZQpoaXN0KGNhbXBzLmRhdGEkY2FtcF90b3RhbCkKCmNhbXAuc2l6ZSA8LSBjYW1wcy5kYXRhICU+JQogIHN1bW1hcmlzZShtZWFuID0gbWVhbihjYW1wX3RvdGFsKSwKICAgICAgICAgICAgc2QgPSBzZChjYW1wX3RvdGFsKSwKICAgICAgICAgICAgbWluID0gbWluKGNhbXBfdG90YWwpLAogICAgICAgICAgICBtYXggPSBtYXgoY2FtcF90b3RhbCksCiAgICAgICAgICAgIHZhciA9IHZhcihjYW1wX3RvdGFsKSkKY2FtcC5zaXplCmBgYAoKCiMjIFNpbmdsZSBQb3B1bGF0aW9uIE1vZGVsCgojIyMgU2V0LXVwCgpgYGB7cn0KIyBEZWZpbmUgUGFyYW1lbnRlcnMKTiA8LSAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCAxKSAgICAjIFBvcHVsYXRpb24gc2l6ZQppbml0aWFsX2luZmVjdGVkIDwtICAxICAgICMgSW5pdGlhbCBpbmZlY3RlZApzaW1OYW1lIDwtICJTRUlSUyBtb2RlbCIgICAgICAgIyBTaW11bGF0aW9uIG5hbWUKdGYgPC0gMzY1KjMKCiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXMgPC0gbGlzdCgKICBiZXRhID0gMC42LAogIHNpZ21hID0gMC4xNzUsICAgICAgICAgICAgICAgICAgICAgICAgICAjIEUgdG8gSSByYXRlCiAgZ2FtbWEgPSAwLjIsICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBJIHRvIFIgcmF0ZQogIG9tZWdhID0gMS8xODAsICAgICAgICAgICAgICAgICAgICAgICAgICMgUiB0byBTIHJhdGUKICBtdSA9IGRlbW9fc3VtJEJpcnRoX3JhdGVfZGFpbHlfTWVhbiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBCaXJ0aC9kZWF0aCByYXRlIHBlciBwZXJzb24gcGVyIGRheQogIGFscGhhID0gMS8xMDAwKSAKCiNDcmVhdGUgdGhlIG5hbWVkIGluaXRpYWwgc3RhdGUgdmVjdG9yIGZvciB0aGUgVS1wYXRjaCBzeXN0ZW0uCgp4MCA8LSBjKE4gLSBpbml0aWFsX2luZmVjdGVkLCBpbml0aWFsX2luZmVjdGVkLCAwLCAwLCBOKQoKbmFtZXMoeDApIDwtIGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKQoKCiMgRGVmaW5lIHRoZSBzdGF0ZSBjaGFuZ2UgbWF0cml4IGZvciBhIHNpbmdsZSBwYXRjaApudSA8LSBtYXRyaXgoYyggLTEsICAwLCAgMCwgKzEsICsxLCAtMSwgIDAsICAwLCAgMCwgIDAsICMgUwogICAgICAgICAgICAgICAgKzEsIC0xLCAgMCwgIDAsICAwLCAgMCwgLTEsICAwLCAgMCwgIDAsICMgRQogICAgICAgICAgICAgICAgMCwgKzEsIC0xLCAgMCwgIDAsICAwLCAgMCwgLTEsICAwLCAtMSwgIyBJCiAgICAgICAgICAgICAgICAwLCAgMCwgKzEsIC0xLCAgMCwgIDAsICAwLCAgMCwgLTEsICAwLCAjIFIgCiAgICAgICAgICAgICAgICAwLCAgMCwgIDAsICAwLCArMSwgLTEgLC0xLCAtMSwgLTEsIC0xKSwgIyBOCiAgICAgICAgICAgICBucm93PTUsYnlyb3c9VFJVRSkKCiMgRGVmaW5lIHByb3BlbnNpdHkgZnVuY3Rpb25zCmEgPC1jKAogICAgICAgIHBhc3RlMCgiKGJldGEqSS9OKSpTIiksICMgSW5mZWN0aW9uCiAgICAgICAgcGFzdGUwKCJzaWdtYSpFIiksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBCZWNvbWVzIGluZmVjaW91cwogICAgICAgIHBhc3RlMCgiZ2FtbWEqSSIpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgUmVjb3ZlcnkgZnJvbSBpbmZlY3Rpb24KICAgICAgICBwYXN0ZTAoIm9tZWdhKlIiKSwgICAgICAgIyBMb3NzIG9mIGltbXVuaXR5CiAgICAgICAgcGFzdGUwKCJtdSpOIiksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEJpcnRocwogICAgICAgIHBhc3RlMCgibXUqUyIpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgRGVhdGhzIChTKQogICAgICAgIHBhc3RlMCgibXUqRSIpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgRGVhdGhzIChFKQogICAgICAgIHBhc3RlMCgibXUqSSIpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgRGVhdGhzIChJKQogICAgICAgIHBhc3RlMCgibXUqUiIpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgRGVhdGhzIChSKQogICAgICAgIHBhc3RlMCgiYWxwaGEqSSIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgRGVhdGhzIGZyb20gaW5mZWN0aW9uCiAgICAgICAgCiAgICAgICkKCmBgYAoKRGVmaW5lIGZ1bmN0aW9ucyB0byBjYWxjdWxhdGUgUjAgYW5kIGV4cGVjdGVkIG51bWJlciBvZiBzdXNjZXB0aWJsZXMgYXQgZXF1aWxpYnJpdW0sIGFuZCBjcml0aWNhbCBjb21tdW5pdHkgc2l6ZSAoRGlla21hbm4gZXQgYWwuLCAyMDEyKS4KCmBgYHtyfQogUjAgPC0gZnVuY3Rpb24ocGFybXMpIHsKICAgKHBhcm1zJHNpZ21hLyhwYXJtcyRzaWdtYSArIHBhcm1zJG11KSkgKiAocGFybXMkYmV0YS9wYXJtcyRnYW1tYSArIHBhcm1zJG11ICsgcGFybXMkYWxwaGEpCiB9IAogIApFSUUgPC0gZnVuY3Rpb24oUjAsIHBhcm1zKSB7CiAgeSA9ICgoUjAgLSAxKSAqIHBhcm1zJG9tZWdhKSAvIChwYXJtcyRnYW1tYSAqIFIwKQogIHJldHVybih5KQp9CgpDQ1MgPC0gZnVuY3Rpb24oZXBzaWxvbiwgUjApIHsKICB5ID0gMS8oKGVwc2lsb25eMikqKCgxLSgxL1IwKSleMikpCiAgcmV0dXJuKHkpCn0KYGBgCgojIyMgU2luZ2xlIFBvcHVsYXRpb24gTW9kZWwKYGBge3J9CgojIENhbGN1bGF0ZSBSMCwgZXhwZWN0ZWQgbnVtYmVyIG9mIGluZmVjdGVkcyBhdCBlcXVpbGlicml1bSwgYW5kIENDUwpSMCA8LSBSMChwYXJtcykKUjAKCkVJRSA8LSBFSUUoUjAsIHBhcm1zKQpFSUUKCmVwc2lsb24gPC0gKDUuNy8zNjUpLzIzICMgZHVyYXRpb24gb2YgaW5mZWN0aW9uIGluIHllYXJzIGRpdmlkZWQgYnkgYXZnIGxpZmUgZXhwZWN0YW5jeSAKQ0NTIDwtIENDUyhlcHNpbG9uLCBSMCkgIyBBdmVyYWdlIGxpZmUgZXhwZWN0YW5jeSBhcyBwZXIgS2FwbGFuIChjcnVkZSkKQ0NTCmBgYAoKYGBge3J9CiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoMikKb3V0IDwtIHNzYSgKICB4MCA9IHgwLAogIGEgPSBhLAogIG51ID0gbnUsCiAgcGFybXMgPSBwYXJtcywKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKSAKCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhIDwtIG91dCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKc2luZ2xlX3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGEsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGxhYnMoeD0iVGltZSAoRGF5cykiLAogICAgICAgeT0iTnVtYmVyIG9mIEluZGl2aWR1YWxzIiwgCiAgICAgICBjb2xvdXI9IlN0YXRlIikrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gRUlFLCBsaW5ldHlwZSA9ICdkYXNoZWQnKSArCiAgdGhlbWVfYncoKQoKc2luZ2xlX3Bsb3QKCmdnc2F2ZShmaWxlbmFtZSA9ICJzaW5nbGVfcGxvdC5wZGYiLCAKICAgICAgIHBsb3QgPSBzaW5nbGVfcGxvdCwKICAgICAgIGRldmljZSA9ICJwZGYiLAogICAgICAgd2lkdGggPSA3LCAKICAgICAgIGhlaWdodCA9IDUsCiAgICAgICBwYXRoID0gIi9Vc2Vycy9tYXR0aGV3aG95bGUvR2l0aHViX1JfcHJvamVjdHMvSHVudGVyX0dhdGhlcmVyX21vZGVscyIpCmBgYAoKYGBge3J9CnBsb3RfZGF0YSAlPiUKICBmaWx0ZXIoc3RhdGUgPT0gIkkiKSAlPiUKICBzbGljZV9tYXgoY291bnQpCmBgYAoKCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdCA8LSBsaXN0KCkKc2ltX2xpc3QgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgCiAgTiA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgMSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIAogIHgwIDwtIGMoTiAtIGluaXRpYWxfaW5mZWN0ZWQsIGluaXRpYWxfaW5mZWN0ZWQsIDAsIDAsIE4pCgogIG5hbWVzKHgwKSA8LSBjKCJTIiwiRSIsIkkiLCAiUiIsICJOIikKCgogIHNldC5zZWVkKGkpCiAgb3V0XzEwMCA8LSBzc2EoCiAgICB4MCA9IHgwLAogICAgYSA9IGEsCiAgICBudSA9IG51LAogICAgcGFybXMgPSBwYXJtcywKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhIDwtIG91dF8xMDAkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0W1tpXV0gPC0gc2ltX2RhdGEKfQoKc2ltX291dHB1dCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3QpCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXQgPC0gc2ltX291dHB1dCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXQKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeSA8LSBzaW1fb3V0cHV0ICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsIAogICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvMTgwKQpzaW1fc3VtbWFyeQpgYGAKIyMjIFZhcnlpbmcgd2FpbmluZyBpbW11bml0eQojIyMjIDAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc18wIDwtIHBhcm1zCnBhcm1zXzAkb21lZ2EgPC0gMAoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0XzAgPC0gc3NhKAogIHgwID0geDAsCiAgYSA9IGEsCiAgbnUgPSBudSwKICBwYXJtcyA9IHBhcm1zXzAsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBFeHRyYSBQbG90cwpwbG90X2RhdGFfMCA8LSBvdXRfMCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF8wIDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhXzAsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfMApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0XzAgPC0gbGlzdCgpCnNpbV9saXN0XzAgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBOIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCAxKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgCiAgeDAgPC0gYyhOIC0gaW5pdGlhbF9pbmZlY3RlZCwgaW5pdGlhbF9pbmZlY3RlZCwgMCwgMCwgTikKCiAgbmFtZXMoeDApIDwtIGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKQoKCiAgb3V0XzEwMF8wIDwtIHNzYSgKICAgIHgwID0geDAsCiAgICBhID0gYSwKICAgIG51ID0gbnUsCiAgICBwYXJtcyA9IHBhcm1zXzAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV8wIDwtIG91dF8xMDBfMCRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJzdGF0ZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIEksIE4sIHBlcnNpc3QpCiAgCiAgc2ltX2xpc3RfMFtbaV1dIDwtIHNpbV9kYXRhXzAKfQoKc2ltX291dHB1dF8wIDwtIGJpbmRfcm93cyhzaW1fbGlzdF8wKQpgYGAKCmBgYHtyfQojIFN1bW1hcnkgdGFibGUgb2YgZW5kcG9pbnQgZGF0YQpzaW1fb3V0cHV0XzAgPC0gc2ltX291dHB1dF8wICU+JQogIGdyb3VwX2J5KHNpbSkgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX0kgPSBzdW0oSSksIAogICAgICAgICAgICB0b3RhbF9OID0gc3VtKE4pKSAlPiUKICBtdXRhdGUocGVyY2VudF9wZXJzaXN0ID0gdG90YWxfSS8odG90YWxfTikqMTAwLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHRvdGFsX0kgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9JID09IDAgfiBGKSkKc2ltX291dHB1dF8wCgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfMCA8LSBzaW1fb3V0cHV0XzAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QsIG5hLnJtID0gVCkvbnVtX3NpbXMpKjEwMCwgICAgICAgICAgICAgIG1lYW5fcGVyY2VudF9pbmZlY3RlZCA9IG1lYW4ocGVyY2VudF9wZXJzaXN0KSkgJT4lCiAgbXV0YXRlKG9tZWdhID0gMCkKc2ltX3N1bW1hcnlfMApgYGAKCgoKCiMjIyMgMSBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zXzEgPC0gcGFybXMKcGFybXNfMSRvbWVnYSA8LSAxCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfMSA8LSBzc2EoCiAgeDAgPSB4MCwKICBhID0gYSwKICBudSA9IG51LAogIHBhcm1zID0gcGFybXNfMSwKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV8xIDwtIG91dF8xJGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJzdGF0ZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIG11dGF0ZShzdGF0ZSA9IGZhY3RvcihzdGF0ZSwgbGV2ZWxzID0gYygiUyIsICJFIiwgIkkiLCAiUiIsICJOIikpKSAjJT4lCiAgI2ZpbHRlcihzdGF0ZSAhPSAiTiIpCgpwbG90XzEgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfMSwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF8xCmBgYApgYGB7cn0KIyMgUnVuIG11bHRpcGxlIHNpbXVsYXRpb25zIGFuZCBzYXZpbmcgb3V0cHV0Cm51bV9zaW1zIDwtIDEwMDAKc2ltX2xpc3RfMSA8LSBsaXN0KCkKc2ltX2xpc3RfMSA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIE4gPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDEpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICAKICB4MCA8LSBjKE4gLSBpbml0aWFsX2luZmVjdGVkLCBpbml0aWFsX2luZmVjdGVkLCAwLCAwLCBOKQoKICBuYW1lcyh4MCkgPC0gYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpCgoKICBvdXRfMTAwXzEgPC0gc3NhKAogICAgeDAgPSB4MCwKICAgIGEgPSBhLAogICAgbnUgPSBudSwKICAgIHBhcm1zID0gcGFybXNfMSwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhXzEgPC0gb3V0XzEwMF8xJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gInN0YXRlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3RhdGUsIHZhbHVlc19mcm9tID0gY291bnQpICU+JQogICAgbXV0YXRlKHBlcnNpc3QgPSBjYXNlX3doZW4oSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEkgPT0gMCB+IEYpLAogICAgICAgICAgIHNpbSA9IGkpICU+JQogICAgc2VsZWN0KHNpbSwgSSwgTiwgcGVyc2lzdCkKICAKICBzaW1fbGlzdF8xW1tpXV0gPC0gc2ltX2RhdGFfMQp9CgpzaW1fb3V0cHV0XzEgPC0gYmluZF9yb3dzKHNpbV9saXN0XzEpCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfMSA8LSBzaW1fb3V0cHV0XzEgJT4lCiAgZ3JvdXBfYnkoc2ltKSAlPiUKICBzdW1tYXJpc2UodG90YWxfSSA9IHN1bShJKSwgCiAgICAgICAgICAgIHRvdGFsX04gPSBzdW0oTikpICU+JQogIG11dGF0ZShwZXJjZW50X3BlcnNpc3QgPSB0b3RhbF9JLyh0b3RhbF9OKSoxMDAsCiAgICAgICAgIHBlcnNpc3QgPSBjYXNlX3doZW4odG90YWxfSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsX0kgPT0gMCB+IEYpKQpzaW1fb3V0cHV0XzEKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV8xIDwtIHNpbV9vdXRwdXRfMSAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLCAgICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxKQpzaW1fc3VtbWFyeV8xCmBgYAoKCgoKCiMjIyMgMyBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zXzMgPC0gcGFybXMKcGFybXNfMyRvbWVnYSA8LSAxLzMKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF8zIDwtIHNzYSgKICB4MCA9IHgwLAogIGEgPSBhLAogIG51ID0gbnUsCiAgcGFybXMgPSBwYXJtc18zLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhXzMgPC0gb3V0XzMkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gInN0YXRlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfMyA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV8zLCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90XzMKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF8zIDwtIGxpc3QoKQpzaW1fbGlzdF8zIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgTiA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgMSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIAogIHgwIDwtIGMoTiAtIGluaXRpYWxfaW5mZWN0ZWQsIGluaXRpYWxfaW5mZWN0ZWQsIDAsIDAsIE4pCgogIG5hbWVzKHgwKSA8LSBjKCJTIiwiRSIsIkkiLCAiUiIsICJOIikKCgogIG91dF8xMDBfMyA8LSBzc2EoCiAgICB4MCA9IHgwLAogICAgYSA9IGEsCiAgICBudSA9IG51LAogICAgcGFybXMgPSBwYXJtc18zLAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfMyA8LSBvdXRfMTAwXzMkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0XzNbW2ldXSA8LSBzaW1fZGF0YV8zCn0KCnNpbV9vdXRwdXRfMyA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfMykKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF8zIDwtIHNpbV9vdXRwdXRfMyAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfMwoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5XzMgPC0gc2ltX291dHB1dF8zICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvMykKc2ltX3N1bW1hcnlfMwpgYGAKCiMjIyMgNyBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zXzcgPC0gcGFybXMKcGFybXNfNyRvbWVnYSA8LSAxLzcKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF83IDwtIHNzYSgKICB4MCA9IHgwLAogIGEgPSBhLAogIG51ID0gbnUsCiAgcGFybXMgPSBwYXJtc183LAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhXzcgPC0gb3V0XzckZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gInN0YXRlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfNyA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV83LCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90XzcKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF83IDwtIGxpc3QoKQpzaW1fbGlzdF83IDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgTiA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgMSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIAogIHgwIDwtIGMoTiAtIGluaXRpYWxfaW5mZWN0ZWQsIGluaXRpYWxfaW5mZWN0ZWQsIDAsIDAsIE4pCgogIG5hbWVzKHgwKSA8LSBjKCJTIiwiRSIsIkkiLCAiUiIsICJOIikKCgogIG91dF8xMDBfNyA8LSBzc2EoCiAgICB4MCA9IHgwLAogICAgYSA9IGEsCiAgICBudSA9IG51LAogICAgcGFybXMgPSBwYXJtc183LAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfNyA8LSBvdXRfMTAwXzckZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0XzdbW2ldXSA8LSBzaW1fZGF0YV83Cn0KCnNpbV9vdXRwdXRfNyA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfNykKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF83IDwtIHNpbV9vdXRwdXRfNyAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfNwoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5XzcgPC0gc2ltX291dHB1dF83ICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvNykKc2ltX3N1bW1hcnlfNwpgYGAKCiMjIyMgMTAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc18xMCA8LSBwYXJtcwpwYXJtc18xMCRvbWVnYSA8LSAxLzEwCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfMTAgPC0gc3NhKAogIHgwID0geDAsCiAgYSA9IGEsCiAgbnUgPSBudSwKICBwYXJtcyA9IHBhcm1zXzEwLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhXzEwIDwtIG91dF8xMCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF8xMCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV8xMCwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF8xMApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0XzEwIDwtIGxpc3QoKQpzaW1fbGlzdF8xMCA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIE4gPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDEpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICAKICB4MCA8LSBjKE4gLSBpbml0aWFsX2luZmVjdGVkLCBpbml0aWFsX2luZmVjdGVkLCAwLCAwLCBOKQoKICBuYW1lcyh4MCkgPC0gYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpCgoKICBvdXRfMTAwXzEwIDwtIHNzYSgKICAgIHgwID0geDAsCiAgICBhID0gYSwKICAgIG51ID0gbnUsCiAgICBwYXJtcyA9IHBhcm1zXzEwLAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfMTAgPC0gb3V0XzEwMF8xMCRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJzdGF0ZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIEksIE4sIHBlcnNpc3QpCiAgCiAgc2ltX2xpc3RfMTBbW2ldXSA8LSBzaW1fZGF0YV8xMAp9CgpzaW1fb3V0cHV0XzEwIDwtIGJpbmRfcm93cyhzaW1fbGlzdF8xMCkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF8xMCA8LSBzaW1fb3V0cHV0XzEwICU+JQogIGdyb3VwX2J5KHNpbSkgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX0kgPSBzdW0oSSksIAogICAgICAgICAgICB0b3RhbF9OID0gc3VtKE4pKSAlPiUKICBtdXRhdGUocGVyY2VudF9wZXJzaXN0ID0gdG90YWxfSS8odG90YWxfTikqMTAwLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHRvdGFsX0kgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9JID09IDAgfiBGKSkKc2ltX291dHB1dF8xMAoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5XzEwIDwtIHNpbV9vdXRwdXRfMTAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QsIG5hLnJtID0gVCkvbnVtX3NpbXMpKjEwMCwgICAgICAgICAgICAgIG1lYW5fcGVyY2VudF9pbmZlY3RlZCA9IG1lYW4ocGVyY2VudF9wZXJzaXN0KSkgJT4lCiAgbXV0YXRlKG9tZWdhID0gMS8xMCkKc2ltX3N1bW1hcnlfMTAKYGBgCgojIyMjIDIwIERheXMKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfMjAgPC0gcGFybXMKcGFybXNfMjAkb21lZ2EgPC0gMS8yMAoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0XzIwIDwtIHNzYSgKICB4MCA9IHgwLAogIGEgPSBhLAogIG51ID0gbnUsCiAgcGFybXMgPSBwYXJtc18yMCwKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV8yMCA8LSBvdXRfMjAkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gInN0YXRlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfMjAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfMjAsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfMjAKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF8yMCA8LSBsaXN0KCkKc2ltX2xpc3RfMjAgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBOIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCAxKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgCiAgeDAgPC0gYyhOIC0gaW5pdGlhbF9pbmZlY3RlZCwgaW5pdGlhbF9pbmZlY3RlZCwgMCwgMCwgTikKCiAgbmFtZXMoeDApIDwtIGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKQoKCiAgb3V0XzEwMF8yMCA8LSBzc2EoCiAgICB4MCA9IHgwLAogICAgYSA9IGEsCiAgICBudSA9IG51LAogICAgcGFybXMgPSBwYXJtc18yMCwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhXzIwIDwtIG91dF8xMDBfMjAkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0XzIwW1tpXV0gPC0gc2ltX2RhdGFfMjAKfQoKc2ltX291dHB1dF8yMCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfMjApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfMjAgPC0gc2ltX291dHB1dF8yMCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfMjAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV8yMCA8LSBzaW1fb3V0cHV0XzIwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvMjApCnNpbV9zdW1tYXJ5XzIwCmBgYAoKIyMjIyAzMCBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zXzMwIDwtIHBhcm1zCnBhcm1zXzMwJG9tZWdhIDwtIDEvMzAKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF8zMCA8LSBzc2EoCiAgeDAgPSB4MCwKICBhID0gYSwKICBudSA9IG51LAogIHBhcm1zID0gcGFybXNfMzAsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBFeHRyYSBQbG90cwpwbG90X2RhdGFfMzAgPC0gb3V0XzMwJGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJzdGF0ZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIG11dGF0ZShzdGF0ZSA9IGZhY3RvcihzdGF0ZSwgbGV2ZWxzID0gYygiUyIsICJFIiwgIkkiLCAiUiIsICJOIikpKSAjJT4lCiAgI2ZpbHRlcihzdGF0ZSAhPSAiTiIpCgpwbG90XzMwIDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhXzMwLCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90XzMwCmBgYApgYGB7cn0KIyMgUnVuIG11bHRpcGxlIHNpbXVsYXRpb25zIGFuZCBzYXZpbmcgb3V0cHV0Cm51bV9zaW1zIDwtIDEwMDAKc2ltX2xpc3RfMzAgPC0gbGlzdCgpCnNpbV9saXN0XzMwIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgTiA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgMSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIAogIHgwIDwtIGMoTiAtIGluaXRpYWxfaW5mZWN0ZWQsIGluaXRpYWxfaW5mZWN0ZWQsIDAsIDAsIE4pCgogIG5hbWVzKHgwKSA8LSBjKCJTIiwiRSIsIkkiLCAiUiIsICJOIikKCgogIG91dF8xMDBfMzAgPC0gc3NhKAogICAgeDAgPSB4MCwKICAgIGEgPSBhLAogICAgbnUgPSBudSwKICAgIHBhcm1zID0gcGFybXNfMzAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV8zMCA8LSBvdXRfMTAwXzMwJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gInN0YXRlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3RhdGUsIHZhbHVlc19mcm9tID0gY291bnQpICU+JQogICAgbXV0YXRlKHBlcnNpc3QgPSBjYXNlX3doZW4oSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEkgPT0gMCB+IEYpLAogICAgICAgICAgIHNpbSA9IGkpICU+JQogICAgc2VsZWN0KHNpbSwgSSwgTiwgcGVyc2lzdCkKICAKICBzaW1fbGlzdF8zMFtbaV1dIDwtIHNpbV9kYXRhXzMwCn0KCnNpbV9vdXRwdXRfMzAgPC0gYmluZF9yb3dzKHNpbV9saXN0XzMwKQpgYGAKCmBgYHtyfQojIFN1bW1hcnkgdGFibGUgb2YgZW5kcG9pbnQgZGF0YQpzaW1fb3V0cHV0XzMwIDwtIHNpbV9vdXRwdXRfMzAgJT4lCiAgZ3JvdXBfYnkoc2ltKSAlPiUKICBzdW1tYXJpc2UodG90YWxfSSA9IHN1bShJKSwgCiAgICAgICAgICAgIHRvdGFsX04gPSBzdW0oTikpICU+JQogIG11dGF0ZShwZXJjZW50X3BlcnNpc3QgPSB0b3RhbF9JLyh0b3RhbF9OKSoxMDAsCiAgICAgICAgIHBlcnNpc3QgPSBjYXNlX3doZW4odG90YWxfSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsX0kgPT0gMCB+IEYpKQpzaW1fb3V0cHV0XzMwCgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfMzAgPC0gc2ltX291dHB1dF8zMCAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLCAgICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxLzMwKQpzaW1fc3VtbWFyeV8zMApgYGAKCiMjIyMgNDAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc180MCA8LSBwYXJtcwpwYXJtc180MCRvbWVnYSA8LSAxLzQwCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfNDAgPC0gc3NhKAogIHgwID0geDAsCiAgYSA9IGEsCiAgbnUgPSBudSwKICBwYXJtcyA9IHBhcm1zXzQwLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhXzQwIDwtIG91dF80MCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF80MCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV80MCwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF80MApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0XzQwIDwtIGxpc3QoKQpzaW1fbGlzdF80MCA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIE4gPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDEpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICAKICB4MCA8LSBjKE4gLSBpbml0aWFsX2luZmVjdGVkLCBpbml0aWFsX2luZmVjdGVkLCAwLCAwLCBOKQoKICBuYW1lcyh4MCkgPC0gYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpCgoKICBvdXRfMTAwXzQwIDwtIHNzYSgKICAgIHgwID0geDAsCiAgICBhID0gYSwKICAgIG51ID0gbnUsCiAgICBwYXJtcyA9IHBhcm1zXzQwLAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfNDAgPC0gb3V0XzEwMF80MCRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJzdGF0ZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIEksIE4sIHBlcnNpc3QpCiAgCiAgc2ltX2xpc3RfNDBbW2ldXSA8LSBzaW1fZGF0YV80MAp9CgpzaW1fb3V0cHV0XzQwIDwtIGJpbmRfcm93cyhzaW1fbGlzdF80MCkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF80MCA8LSBzaW1fb3V0cHV0XzQwICU+JQogIGdyb3VwX2J5KHNpbSkgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX0kgPSBzdW0oSSksIAogICAgICAgICAgICB0b3RhbF9OID0gc3VtKE4pKSAlPiUKICBtdXRhdGUocGVyY2VudF9wZXJzaXN0ID0gdG90YWxfSS8odG90YWxfTikqMTAwLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHRvdGFsX0kgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9JID09IDAgfiBGKSkKc2ltX291dHB1dF80MAoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5XzQwIDwtIHNpbV9vdXRwdXRfNDAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QsIG5hLnJtID0gVCkvbnVtX3NpbXMpKjEwMCwgICAgICAgICAgICAgIG1lYW5fcGVyY2VudF9pbmZlY3RlZCA9IG1lYW4ocGVyY2VudF9wZXJzaXN0KSkgJT4lCiAgbXV0YXRlKG9tZWdhID0gMS80MCkKc2ltX3N1bW1hcnlfNDAKYGBgCgojIyMjIDUwIERheXMKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfNTAgPC0gcGFybXMKcGFybXNfNTAkb21lZ2EgPC0gMS81MAoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0XzUwIDwtIHNzYSgKICB4MCA9IHgwLAogIGEgPSBhLAogIG51ID0gbnUsCiAgcGFybXMgPSBwYXJtc181MCwKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV81MCA8LSBvdXRfNTAkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gInN0YXRlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfNTAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfNTAsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfNTAKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF81MCA8LSBsaXN0KCkKc2ltX2xpc3RfNTAgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBOIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCAxKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgCiAgeDAgPC0gYyhOIC0gaW5pdGlhbF9pbmZlY3RlZCwgaW5pdGlhbF9pbmZlY3RlZCwgMCwgMCwgTikKCiAgbmFtZXMoeDApIDwtIGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKQoKCiAgb3V0XzEwMF81MCA8LSBzc2EoCiAgICB4MCA9IHgwLAogICAgYSA9IGEsCiAgICBudSA9IG51LAogICAgcGFybXMgPSBwYXJtc181MCwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhXzUwIDwtIG91dF8xMDBfNTAkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0XzUwW1tpXV0gPC0gc2ltX2RhdGFfNTAKfQoKc2ltX291dHB1dF81MCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfNTApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfNTAgPC0gc2ltX291dHB1dF81MCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfNTAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV81MCA8LSBzaW1fb3V0cHV0XzUwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvNTApCnNpbV9zdW1tYXJ5XzUwCmBgYAoKIyMjIyA2MCBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zXzYwIDwtIHBhcm1zCnBhcm1zXzYwJG9tZWdhIDwtIDEvNjAKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF82MCA8LSBzc2EoCiAgeDAgPSB4MCwKICBhID0gYSwKICBudSA9IG51LAogIHBhcm1zID0gcGFybXNfNjAsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBFeHRyYSBQbG90cwpwbG90X2RhdGFfNjAgPC0gb3V0XzYwJGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJzdGF0ZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIG11dGF0ZShzdGF0ZSA9IGZhY3RvcihzdGF0ZSwgbGV2ZWxzID0gYygiUyIsICJFIiwgIkkiLCAiUiIsICJOIikpKSAjJT4lCiAgI2ZpbHRlcihzdGF0ZSAhPSAiTiIpCgpwbG90XzYwIDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhXzYwLCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90XzYwCmBgYApgYGB7cn0KIyMgUnVuIG11bHRpcGxlIHNpbXVsYXRpb25zIGFuZCBzYXZpbmcgb3V0cHV0Cm51bV9zaW1zIDwtIDEwMDAKc2ltX2xpc3RfNjAgPC0gbGlzdCgpCnNpbV9saXN0XzYwIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgTiA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgMSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIAogIHgwIDwtIGMoTiAtIGluaXRpYWxfaW5mZWN0ZWQsIGluaXRpYWxfaW5mZWN0ZWQsIDAsIDAsIE4pCgogIG5hbWVzKHgwKSA8LSBjKCJTIiwiRSIsIkkiLCAiUiIsICJOIikKCgogIG91dF8xMDBfNjAgPC0gc3NhKAogICAgeDAgPSB4MCwKICAgIGEgPSBhLAogICAgbnUgPSBudSwKICAgIHBhcm1zID0gcGFybXNfNjAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV82MCA8LSBvdXRfMTAwXzYwJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gInN0YXRlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3RhdGUsIHZhbHVlc19mcm9tID0gY291bnQpICU+JQogICAgbXV0YXRlKHBlcnNpc3QgPSBjYXNlX3doZW4oSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEkgPT0gMCB+IEYpLAogICAgICAgICAgIHNpbSA9IGkpICU+JQogICAgc2VsZWN0KHNpbSwgSSwgTiwgcGVyc2lzdCkKICAKICBzaW1fbGlzdF82MFtbaV1dIDwtIHNpbV9kYXRhXzYwCn0KCnNpbV9vdXRwdXRfNjAgPC0gYmluZF9yb3dzKHNpbV9saXN0XzYwKQpgYGAKCmBgYHtyfQojIFN1bW1hcnkgdGFibGUgb2YgZW5kcG9pbnQgZGF0YQpzaW1fb3V0cHV0XzYwIDwtIHNpbV9vdXRwdXRfNjAgJT4lCiAgZ3JvdXBfYnkoc2ltKSAlPiUKICBzdW1tYXJpc2UodG90YWxfSSA9IHN1bShJKSwgCiAgICAgICAgICAgIHRvdGFsX04gPSBzdW0oTikpICU+JQogIG11dGF0ZShwZXJjZW50X3BlcnNpc3QgPSB0b3RhbF9JLyh0b3RhbF9OKSoxMDAsCiAgICAgICAgIHBlcnNpc3QgPSBjYXNlX3doZW4odG90YWxfSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsX0kgPT0gMCB+IEYpKQpzaW1fb3V0cHV0XzYwCgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfNjAgPC0gc2ltX291dHB1dF82MCAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLCAgICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxLzYwKQpzaW1fc3VtbWFyeV82MApgYGAKCiMjIyMgNzAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc183MCA8LSBwYXJtcwpwYXJtc183MCRvbWVnYSA8LSAxLzcwCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfNzAgPC0gc3NhKAogIHgwID0geDAsCiAgYSA9IGEsCiAgbnUgPSBudSwKICBwYXJtcyA9IHBhcm1zXzcwLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhXzcwIDwtIG91dF83MCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF83MCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV83MCwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF83MApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0XzcwIDwtIGxpc3QoKQpzaW1fbGlzdF83MCA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIE4gPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDEpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICAKICB4MCA8LSBjKE4gLSBpbml0aWFsX2luZmVjdGVkLCBpbml0aWFsX2luZmVjdGVkLCAwLCAwLCBOKQoKICBuYW1lcyh4MCkgPC0gYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpCgoKICBvdXRfMTAwXzcwIDwtIHNzYSgKICAgIHgwID0geDAsCiAgICBhID0gYSwKICAgIG51ID0gbnUsCiAgICBwYXJtcyA9IHBhcm1zXzcwLAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfNzAgPC0gb3V0XzEwMF83MCRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJzdGF0ZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIEksIE4sIHBlcnNpc3QpCiAgCiAgc2ltX2xpc3RfNzBbW2ldXSA8LSBzaW1fZGF0YV83MAp9CgpzaW1fb3V0cHV0XzcwIDwtIGJpbmRfcm93cyhzaW1fbGlzdF83MCkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF83MCA8LSBzaW1fb3V0cHV0XzcwICU+JQogIGdyb3VwX2J5KHNpbSkgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX0kgPSBzdW0oSSksIAogICAgICAgICAgICB0b3RhbF9OID0gc3VtKE4pKSAlPiUKICBtdXRhdGUocGVyY2VudF9wZXJzaXN0ID0gdG90YWxfSS8odG90YWxfTikqMTAwLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHRvdGFsX0kgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9JID09IDAgfiBGKSkKc2ltX291dHB1dF83MAoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5XzcwIDwtIHNpbV9vdXRwdXRfNzAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QpL251bV9zaW1zKSoxMDAsCiAgICAgICAgICAgIG1lYW5fcGVyY2VudF9pbmZlY3RlZCA9IG1lYW4ocGVyY2VudF9wZXJzaXN0KSkgJT4lCiAgbXV0YXRlKG9tZWdhID0gMS83MCkKc2ltX3N1bW1hcnlfNzAKYGBgCgojIyMjIDgwIERheXMKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfODAgPC0gcGFybXMKcGFybXNfODAkb21lZ2EgPC0gMS84MAoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0XzgwIDwtIHNzYSgKICB4MCA9IHgwLAogIGEgPSBhLAogIG51ID0gbnUsCiAgcGFybXMgPSBwYXJtc184MCwKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV84MCA8LSBvdXRfODAkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gInN0YXRlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfODAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfODAsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfODAKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF84MCA8LSBsaXN0KCkKc2ltX2xpc3RfODAgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBOIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCAxKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgCiAgeDAgPC0gYyhOIC0gaW5pdGlhbF9pbmZlY3RlZCwgaW5pdGlhbF9pbmZlY3RlZCwgMCwgMCwgTikKCiAgbmFtZXMoeDApIDwtIGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKQoKCiAgb3V0XzEwMF84MCA8LSBzc2EoCiAgICB4MCA9IHgwLAogICAgYSA9IGEsCiAgICBudSA9IG51LAogICAgcGFybXMgPSBwYXJtc184MCwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhXzgwIDwtIG91dF8xMDBfODAkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0XzgwW1tpXV0gPC0gc2ltX2RhdGFfODAKfQoKc2ltX291dHB1dF84MCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfODApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfODAgPC0gc2ltX291dHB1dF84MCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfODAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV84MCA8LSBzaW1fb3V0cHV0XzgwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvODApCnNpbV9zdW1tYXJ5XzgwCmBgYAoKIyMjIyAxMDAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc18xMDAgPC0gcGFybXMKcGFybXNfMTAwJG9tZWdhIDwtIDEvMTAwCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfMTAwIDwtIHNzYSgKICB4MCA9IHgwLAogIGEgPSBhLAogIG51ID0gbnUsCiAgcGFybXMgPSBwYXJtc18xMDAsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBFeHRyYSBQbG90cwpwbG90X2RhdGFfMTAwIDwtIG91dF8xMDAkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gInN0YXRlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfMTAwIDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhXzEwMCwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF8xMDAKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF8xMDAgPC0gbGlzdCgpCnNpbV9saXN0XzEwMCA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIE4gPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDEpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICAKICB4MCA8LSBjKE4gLSBpbml0aWFsX2luZmVjdGVkLCBpbml0aWFsX2luZmVjdGVkLCAwLCAwLCBOKQoKICBuYW1lcyh4MCkgPC0gYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpCgoKICBvdXRfMTAwXzEwMCA8LSBzc2EoCiAgICB4MCA9IHgwLAogICAgYSA9IGEsCiAgICBudSA9IG51LAogICAgcGFybXMgPSBwYXJtc18xMDAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV8xMDAgPC0gb3V0XzEwMF8xMDAkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0XzEwMFtbaV1dIDwtIHNpbV9kYXRhXzEwMAp9CgpzaW1fb3V0cHV0XzEwMCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfMTAwKQpgYGAKCmBgYHtyfQojIFN1bW1hcnkgdGFibGUgb2YgZW5kcG9pbnQgZGF0YQpzaW1fb3V0cHV0XzEwMCA8LSBzaW1fb3V0cHV0XzEwMCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfMTAwCgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfMTAwIDwtIHNpbV9vdXRwdXRfMTAwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvMTAwKQpzaW1fc3VtbWFyeV8xMDAKYGBgCgojIyMjIDE1MCBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zXzE1MCA8LSBwYXJtcwpwYXJtc18xNTAkb21lZ2EgPC0gMS8xNTAKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF8xNTAgPC0gc3NhKAogIHgwID0geDAsCiAgYSA9IGEsCiAgbnUgPSBudSwKICBwYXJtcyA9IHBhcm1zXzE1MCwKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV8xNTAgPC0gb3V0XzE1MCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAic3RhdGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF8xNTAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfMTUwLCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90XzE1MApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0XzE1MCA8LSBsaXN0KCkKc2ltX2xpc3RfMTUwIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgTiA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgMSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIAogIHgwIDwtIGMoTiAtIGluaXRpYWxfaW5mZWN0ZWQsIGluaXRpYWxfaW5mZWN0ZWQsIDAsIDAsIE4pCgogIG5hbWVzKHgwKSA8LSBjKCJTIiwiRSIsIkkiLCAiUiIsICJOIikKCgogIG91dF8xMDBfMTUwIDwtIHNzYSgKICAgIHgwID0geDAsCiAgICBhID0gYSwKICAgIG51ID0gbnUsCiAgICBwYXJtcyA9IHBhcm1zXzE1MCwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhXzE1MCA8LSBvdXRfMTAwXzE1MCRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJzdGF0ZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIEksIE4sIHBlcnNpc3QpCiAgCiAgc2ltX2xpc3RfMTUwW1tpXV0gPC0gc2ltX2RhdGFfMTUwCn0KCnNpbV9vdXRwdXRfMTUwIDwtIGJpbmRfcm93cyhzaW1fbGlzdF8xNTApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfMTUwIDwtIHNpbV9vdXRwdXRfMTUwICU+JQogIGdyb3VwX2J5KHNpbSkgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX0kgPSBzdW0oSSksIAogICAgICAgICAgICB0b3RhbF9OID0gc3VtKE4pKSAlPiUKICBtdXRhdGUocGVyY2VudF9wZXJzaXN0ID0gdG90YWxfSS8odG90YWxfTikqMTAwLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHRvdGFsX0kgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9JID09IDAgfiBGKSkKc2ltX291dHB1dF8xNTAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV8xNTAgPC0gc2ltX291dHB1dF8xNTAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QsIG5hLnJtID0gVCkvbnVtX3NpbXMpKjEwMCwgICAgICAgICAgICAgIG1lYW5fcGVyY2VudF9pbmZlY3RlZCA9IG1lYW4ocGVyY2VudF9wZXJzaXN0KSkgJT4lCiAgbXV0YXRlKG9tZWdhID0gMS8xNTApCnNpbV9zdW1tYXJ5XzE1MApgYGAKCiMjIyMgMzY1IERheXMKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfMzY1IDwtIHBhcm1zCnBhcm1zXzM2NSRvbWVnYSA8LSAxLzM2NQoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0XzM2NSA8LSBzc2EoCiAgeDAgPSB4MCwKICBhID0gYSwKICBudSA9IG51LAogIHBhcm1zID0gcGFybXNfMzY1LAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhXzM2NSA8LSBvdXRfMzY1JGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJzdGF0ZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIG11dGF0ZShzdGF0ZSA9IGZhY3RvcihzdGF0ZSwgbGV2ZWxzID0gYygiUyIsICJFIiwgIkkiLCAiUiIsICJOIikpKSAjJT4lCiAgI2ZpbHRlcihzdGF0ZSAhPSAiTiIpCgpwbG90XzM2NSA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV8zNjUsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfMzY1CmBgYApgYGB7cn0KIyMgUnVuIG11bHRpcGxlIHNpbXVsYXRpb25zIGFuZCBzYXZpbmcgb3V0cHV0Cm51bV9zaW1zIDwtIDEwMDAKc2ltX2xpc3RfMzY1IDwtIGxpc3QoKQpzaW1fbGlzdF8zNjUgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBOIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCAxKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgCiAgeDAgPC0gYyhOIC0gaW5pdGlhbF9pbmZlY3RlZCwgaW5pdGlhbF9pbmZlY3RlZCwgMCwgMCwgTikKCiAgbmFtZXMoeDApIDwtIGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKQoKCiAgb3V0XzEwMF8zNjUgPC0gc3NhKAogICAgeDAgPSB4MCwKICAgIGEgPSBhLAogICAgbnUgPSBudSwKICAgIHBhcm1zID0gcGFybXNfMzY1LAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfMzY1IDwtIG91dF8xMDBfMzY1JGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gInN0YXRlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3RhdGUsIHZhbHVlc19mcm9tID0gY291bnQpICU+JQogICAgbXV0YXRlKHBlcnNpc3QgPSBjYXNlX3doZW4oSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEkgPT0gMCB+IEYpLAogICAgICAgICAgIHNpbSA9IGkpICU+JQogICAgc2VsZWN0KHNpbSwgSSwgTiwgcGVyc2lzdCkKICAKICBzaW1fbGlzdF8zNjVbW2ldXSA8LSBzaW1fZGF0YV8zNjUKfQoKc2ltX291dHB1dF8zNjUgPC0gYmluZF9yb3dzKHNpbV9saXN0XzM2NSkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF8zNjUgPC0gc2ltX291dHB1dF8zNjUgJT4lCiAgZ3JvdXBfYnkoc2ltKSAlPiUKICBzdW1tYXJpc2UodG90YWxfSSA9IHN1bShJKSwgCiAgICAgICAgICAgIHRvdGFsX04gPSBzdW0oTikpICU+JQogIG11dGF0ZShwZXJjZW50X3BlcnNpc3QgPSB0b3RhbF9JLyh0b3RhbF9OKSoxMDAsCiAgICAgICAgIHBlcnNpc3QgPSBjYXNlX3doZW4odG90YWxfSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsX0kgPT0gMCB+IEYpKQpzaW1fb3V0cHV0XzM2NQoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5XzM2NSA8LSBzaW1fb3V0cHV0XzM2NSAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLCAgICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxLzM2NSkKc2ltX3N1bW1hcnlfMzY1CmBgYAoKCgojIyMjIFJlc3VsdHMKYGBge3J9CndhbmluZ19yZXN1bHRzX3NpbmdsZSA8LSBzaW1fc3VtbWFyeSAlPiUKICBiaW5kX3Jvd3Moc2ltX3N1bW1hcnlfMSkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5XzMpICU+JQogIGJpbmRfcm93cyhzaW1fc3VtbWFyeV83KSAlPiUKICBiaW5kX3Jvd3Moc2ltX3N1bW1hcnlfMTApICU+JQogIGJpbmRfcm93cyhzaW1fc3VtbWFyeV8yMCkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5XzMwKSAlPiUKICBiaW5kX3Jvd3Moc2ltX3N1bW1hcnlfNDApICU+JQogIGJpbmRfcm93cyhzaW1fc3VtbWFyeV81MCkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5XzYwKSAlPiUKICBiaW5kX3Jvd3Moc2ltX3N1bW1hcnlfNzApICU+JQogIGJpbmRfcm93cyhzaW1fc3VtbWFyeV84MCkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5XzEwMCkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5XzE1MCkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5XzM2NSkgJT4lCiAgbXV0YXRlKGltbXVuaXR5X2R1cmF0aW9uID0gMS9vbWVnYSkgJT4lCiAgYXJyYW5nZShpbW11bml0eV9kdXJhdGlvbikgJT4lCiAgbXV0YXRlKG1vZGVsPSJzaW5nbGUiKQoKd3JpdGVfY3N2KHdhbmluZ19yZXN1bHRzX3NpbmdsZSwgZmlsZSA9ICIvVXNlcnMvbWF0dGhld2hveWxlL0dpdGh1Yl9SX3Byb2plY3RzL0h1bnRlcl9HYXRoZXJlcl9tb2RlbHMvd2FuaW5nX3Jlc3VsdHNfc2luZ2xlLmNzdiIpCgp3YW5pbmdfcmVzdWx0c19zaW5nbGUKCmBgYAoKYGBge3J9CmdncGxvdCh3YW5pbmdfcmVzdWx0c19zaW5nbGUsIGFlcyhpbW11bml0eV9kdXJhdGlvbiwgc3VtX3BlcnNpc3QpKSArCiAgZ2VvbV9saW5lKCkrCiAgZ2VvbV9wb2ludCgpKwogIHRoZW1lX2J3KCkKYGBgCgoKCgojIyBNZXRhcG9wdWxhdGlvbiBNb2RlbCAKCiMjI1NldC11cAoKYGBge3J9CiMgRGVmaW5lIFBhcmFtZW50ZXJzCnBhdGNoUG9wU2l6ZSA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgNywgcmVwbGFjZSA9IFRSVUUpICAgICMgUGF0Y2ggc2l6ZQpVIDwtIGxlbmd0aChwYXRjaFBvcFNpemUpICAgICAgICAgICAgICAgICAgICAjIE51bWJlciBvZiBwYXRjaGVzCmluaXRpYWxfaW5mZWN0ZWQgPC0gIGFzLnZlY3RvcihybXVsdGlub20oMSwgMSwgcmVwKDAuNSwgVSkpKSAgICMgSW5pdGlhbCBpbmZlY3RlZCAoaW5pdGlhbCBpbmZlY3RlZCBwYXRjaCByYW5kb21seSBnZW5lcmF0ZWQpCmluaXRpYWxfaW5mZWN0ZWRfcGF0Y2ggPC0gd2hpY2goaW5pdGlhbF9pbmZlY3RlZCA+IDApCnNpbU5hbWUgPC0gIlNJUlMgbWV0YXBvcHVsYXRpb24gbW9kZWwiICAgICAgICMgU2ltdWxhdGlvbiBuYW1lCnRmIDwtIDM2NSozICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEZpbmFsIHRpbWUKCiMgQWd0YSBIdW50ZXItR2F0aGVyZXIgY29udGFjdCByYXRlcwp3aXRoaW5fcG9wX2NvbnRhY3QgPSAxCmJldHdlZW5fcG9wX2NvbnRhY3QgPSAwLjUvVSAgICAgIyBub3JtYWxpc2VkIGJ5IG51bWJlciBvZiBwYXRjaGVzIAoKI0NyZWF0ZSB0aGUgbmFtZWQgaW5pdGlhbCBzdGF0ZSB2ZWN0b3IgZm9yIHRoZSBVLXBhdGNoIHN5c3RlbS4KCngwX21ldGEgPC0gdW5saXN0KGxhcHBseSgKICBzZXFfbGVuKFUpLCAKICBmdW5jdGlvbihpKXsgCiAgICBjKHBhdGNoUG9wU2l6ZVtpXSAtIGluaXRpYWxfaW5mZWN0ZWRbaV0sIGluaXRpYWxfaW5mZWN0ZWRbaV0sIDAsIDAsIHBhdGNoUG9wU2l6ZVtpXSkKICB9CikpCgpuYW1lcyh4MF9tZXRhKSA8LSB1bmxpc3QobGFwcGx5KHNlcV9sZW4oVSksIGZ1bmN0aW9uKGkpIHBhc3RlMChjKCJTIiwiRSIsIkkiLCAiUiIsICJOIiksIGkpKSkKCgojIERlZmluZSB0aGUgc3RhdGUgY2hhbmdlIG1hdHJpeCBmb3IgYSBzaW5nbGUgcGF0Y2gKbnVfbWV0YSA8LSBtYXRyaXgoYyggLTEsICAwLCAgMCwgKzEsICsxLCAtMSwgIDAsICAwLCAgMCwgIDAsICMgUwogICAgICAgICAgICAgICAgICAgICArMSwgLTEsICAwLCAgMCwgIDAsICAwLCAtMSwgIDAsICAwLCAgMCwgIyBFCiAgICAgICAgICAgICAgICAgICAgICAwLCArMSwgLTEsICAwLCAgMCwgIDAsICAwLCAtMSwgIDAsIC0xLCAjIEkKICAgICAgICAgICAgICAgICAgICAgIDAsICAwLCArMSwgLTEsICAwLCAgMCwgIDAsICAwLCAtMSwgIDAsICMgUiAKICAgICAgICAgICAgICAgICAgICAgIDAsICAwLCAgMCwgIDAsICsxLCAtMSAsLTEsIC0xLCAtMSwgLTEpLCAjIE4KICAgICAgICAgICAgIG5yb3c9NSxieXJvdz1UUlVFKQoKIyBEZWZpbmUgcHJvcGVuc2l0eSBmdW5jdGlvbnMKIyBNYXNzLWFjdGlvbgphX21ldGEgPC0KICB1bmxpc3QobGFwcGx5KAogICAgc2VxX2xlbihVKSwKICAgIGZ1bmN0aW9uKHBhdGNoKSB7CiAgICAgIGkgPC0gcGF0Y2gKICAgICAgcGF0Y2hlcyA8LSAxOlUKICAgICAgI2ogPC0gaWYgKHBhdGNoID09IDEpIFUgZWxzZSBwYXRjaCAtIDEKICAgICAgb3RoZXJfcGF0Y2hlcyA8LSBwYXRjaGVzWy1pXQogICAgICBwYXRjaF9iZXRhIDwtIGMoKQogICAgICBmb3IoayBpbiAoMTooVS0xKSkpewogICAgICAgIHBhdGNoX2JldGFba10gPSBwYXN0ZTAoIisoYmV0YV8iLCBvdGhlcl9wYXRjaGVzW2tdLGksICIqSSIsIG90aGVyX3BhdGNoZXNba10sICIvTiIsIG90aGVyX3BhdGNoZXNba10sICIpKlMiLCBpKQogICAgICB9CiAgICAgIGMoCiAgICAgICAgcGFzdGUwKCIoYmV0YV8iLCBpLCBpLCAiKkkiLCBpLCIvTiIsIGksICIpKlMiLGksIHBhc3RlMChwYXRjaF9iZXRhLCBjb2xsYXBzZT0iIikpLCAjIEluZmVjdGlvbgogICAgICAgIHBhc3RlMCgic2lnbWEqRSIsIGkpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQmVjb21lcyBpbmZlY2lvdXMKICAgICAgICBwYXN0ZTAoImdhbW1hKkkiLCBpKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFJlY292ZXJ5IGZyb20gaW5mZWN0aW9uCiAgICAgICAgcGFzdGUwKCJvbWVnYSpSIiwgaSksICAgICAgICMgTG9zcyBvZiBpbW11bml0eQogICAgICAgIHBhc3RlMCgibXUqTiIsIGkpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBCaXJ0aHMKICAgICAgICBwYXN0ZTAoIm11KlMiLCBpKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIERlYXRocyAoUykKICAgICAgICBwYXN0ZTAoIm11KkUiLCBpKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIERlYXRocyAoRSkKICAgICAgICBwYXN0ZTAoIm11KkkiLCBpKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIERlYXRocyAoSSkKICAgICAgICBwYXN0ZTAoIm11KlIiLCBpKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIERlYXRocyAoUikKICAgICAgICBwYXN0ZTAoImFscGhhKkkiLCBpKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIERlYXRocyBmcm9tIGluZmVjdGlvbgogICAgICAgIAogICAgICApCiAgICB9CiAgKSkKCmBgYAoKRGVmaW5lIGZ1bmN0aW9ucyBmb3IgY2FsY3VsYXRpbmcgUjAgZnJvbSBuZXh0LWdlbmVyYXRpb24gbWF0cml4CmBgYHtyfQojIENhbGN1bGF0ZSBSMCBmcm9tIE5HTQoKUjBuZ20gPC0gZnVuY3Rpb24obmV4dGdlbl9tYXRyaXgpIHsKICBlaWdlbnZhbHVlcyA9IGVpZ2VuKG5leHRnZW5fbWF0cml4LCBvbmx5LnZhbHVlcyA9IFQpCiAgUjAgPSBtYXgoYWJzKGVpZ2VudmFsdWVzJHZhbHVlcykpCiAgcmV0dXJuKFIwKQp9CgpiZXRhLm5nbSA8LSBmdW5jdGlvbihiZXRhX21hdHJpeCkgewogIGVpZ2VudmFsdWVzID0gZWlnZW4oYmV0YV9tYXRyaXgsIG9ubHkudmFsdWVzID0gVCkKICBiZXRhX25nbSA9IG1heChhYnMoZWlnZW52YWx1ZXMkdmFsdWVzKSkKICByZXR1cm4oYmV0YV9uZ20pCn0KYGBgCgoKCiMjIyBNZXRhcG9wdWxhdGlvbiBNb2RlbApgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc19tZXRhIDwtIGxpc3QoCiAgc2lnbWEgPSAwLjE3NSwgICAgICAgICAgICAgICAgICAgICAgICAgICMgRSB0byBJIHJhdGUKICBnYW1tYSA9IDAuMiwgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEkgdG8gUiByYXRlCiAgb21lZ2EgPSAxLzE4MCwgICAgICAgICAgICAgICAgICAgICAgICAgIyBSIHRvIFMgcmF0ZQogIG11ID0gZGVtb19zdW0kQmlydGhfcmF0ZV9kYWlseV9NZWFuLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEJpcnRoL2RlYXRoIHJhdGUgcGVyIHBlcnNvbiBwZXIgZGF5CiAgYWxwaGEgPSAxLzEwMDApIAoKIyBEZWZpbmUgdHJhbnNtaXNzaW9uIHRlcm1zIGFuZCBwb3B1bGF0ZSBuZXh0LWdlbmVyYXRpb24gbWF0cml4CmJldGEgPC0gMC42CgpuZXh0Z2VuX21hdHJpeCA8LSBtYXRyaXgobnJvdyA9IFUsIG5jb2wgPSBVLCBkYXRhID0gMCkKYmV0YV9tYXRyaXggPC0gbWF0cml4KG5yb3cgPSBVLCBuY29sID0gVSwgZGF0YSA9IDApCgoKZm9yKGkgaW4gMTpVKXsKICBmb3IoaiBpbiAxOlUpewogICAgcGFybXNfbWV0YVtbcGFzdGUwKCJiZXRhXyIsaSxpKV1dID0gd2l0aGluX3BvcF9jb250YWN0KmJldGEKICAgIG5leHRnZW5fbWF0cml4W2ksaV0gPSB3aXRoaW5fcG9wX2NvbnRhY3QqYmV0YSooMS9wYXJtc19tZXRhJGdhbW1hKQogICAgcGFybXNfbWV0YVtbcGFzdGUwKCJiZXRhXyIsaixpKV1dID0gYmV0d2Vlbl9wb3BfY29udGFjdCpiZXRhCiAgICBuZXh0Z2VuX21hdHJpeFtqLGldID0gYmV0d2Vlbl9wb3BfY29udGFjdCpiZXRhKigxL3Bhcm1zX21ldGEkZ2FtbWEpCiAgICBuZXh0Z2VuX21hdHJpeFtpLGpdID0gYmV0d2Vlbl9wb3BfY29udGFjdCpiZXRhKigxL3Bhcm1zX21ldGEkZ2FtbWEpCiAgICBwYXJtc19tZXRhW1twYXN0ZTAoImJldGFfIixqLGopXV0gPSB3aXRoaW5fcG9wX2NvbnRhY3QqYmV0YQogICAgbmV4dGdlbl9tYXRyaXhbaixqXSA9IHdpdGhpbl9wb3BfY29udGFjdCpiZXRhKigxL3Bhcm1zX21ldGEkZ2FtbWEpCiAgICBiZXRhX21hdHJpeFtpLGldID0gd2l0aGluX3BvcF9jb250YWN0KmJldGEKICAgIGJldGFfbWF0cml4W2osaV0gPSBiZXR3ZWVuX3BvcF9jb250YWN0KmJldGEKICAgIGJldGFfbWF0cml4W2ksal0gPSBiZXR3ZWVuX3BvcF9jb250YWN0KmJldGEKICAgIGJldGFfbWF0cml4W2osal0gPSB3aXRoaW5fcG9wX2NvbnRhY3QqYmV0YQogIH0KICBwYXJtc19tZXRhW1twYXN0ZTAoIk4iLCBpKV1dID0gcGF0Y2hQb3BTaXplW2ldCn0KYGBgCgoKYGBge3J9CiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0X21ldGEgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGEsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBQbG90CnBsb3RfZGF0YV9tZXRhIDwtIG91dF9tZXRhJGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIHNlcGFyYXRlKElELCAKICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF9tZXRhIDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhX21ldGEsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGZhY2V0X3dyYXAofmZhY3RvcihwYXRjaCwgbGV2ZWxzID0gdW5pcXVlKHBhdGNoKSkgLG5jb2wgPSAxLCBzY2FsZXMgPSAiZnJlZV95IikrCiAgbGFicyh4PSJUaW1lIChEYXlzKSIsCiAgICAgICB5PSJOdW1iZXIgb2YgSW5kaXZpZHVhbHMiLAogICAgICAgY29sb3VyPSJTdGF0ZSIpKwogIHRoZW1lX2J3KCkKcGxvdF9tZXRhCgpnZ3NhdmUoZmlsZW5hbWUgPSAibWV0YV9wbG90LnBkZiIsIAogICAgICAgcGxvdCA9IHBsb3RfbWV0YSwKICAgICAgIGRldmljZSA9ICJwZGYiLAogICAgICAgd2lkdGggPSA3LCAKICAgICAgIGhlaWdodCA9IDgsCiAgICAgICBwYXRoID0gIi9Vc2Vycy9tYXR0aGV3aG95bGUvR2l0aHViX1JfcHJvamVjdHMvSHVudGVyX0dhdGhlcmVyX21vZGVscyIpCmBgYAoKYGBge3J9CiMjIFRhYmxlIHNob3dpbmcgZXh0aW5jdGlvbi90cmFuc21pc3Npb24gaW5mbyBmb3IgZWFjaCBwYXRjaAoKZXh0aW5jdF9kYXRhX21ldGEgPC0gb3V0X21ldGEkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBzbGljZV9tYXgodCkgJT4lCiAgZGlzdGluY3QoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogIG11dGF0ZShzdGF0ZSA9IGZhY3RvcihzdGF0ZSwgbGV2ZWxzID0gYygiUyIsICJFIiwgIkkiLCAiUiIsICJOIikpLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHN0YXRlPT0iSSIgJiBjb3VudCA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZT09IkkiICYgY291bnQgPT0gMCB+IEYpKSAlPiUKICBkcm9wX25hKCkgJT4lCiAgc2VsZWN0KHBhdGNoLCBjb3VudCwgcGVyc2lzdCkKZXh0aW5jdF9kYXRhX21ldGEKYGBgCgoKYGBge3J9CmJldGFfbWV0YSA8LSBiZXRhLm5nbShiZXRhX21hdHJpeCkKcGFzdGUwKCJCZXRhIGZvciB3aG9sZSBzeXN0ZW0gPSAiLCBiZXRhX21ldGEpCgoKUjBfbWV0YSA8LSBSMG5nbShuZXh0Z2VuX21hdHJpeCkKcGFzdGUwKCJSMCA9ICIsIFIwX21ldGEpCgoKcGFzdGUwKCJBY3R1YWwgbnVtYmVyIG9mIGluZmVjdGVkcyBhdCBlbmQgb2Ygc2ltID0gIiwgc3VtKGV4dGluY3RfZGF0YV9tZXRhJGNvdW50KSkKICMgVG90YWwgbnVtYmVyIG9mIGluZmVjdGVkcyBhdCB0aGUgZW5kIG9mIHNpbSBhY3Jvc3MgYWxsIHBhdGNoZXMKCnNpbV9lbmRwb2ludF9tZXRhIDwtIGFzX3RpYmJsZShvdXRfbWV0YSRkYXRhKSAlPiUKICBzbGljZV9tYXgodCkgJT4lCiAgZGlzdGluY3QoKQoKCnBhc3RlMCgiRGlkIHNpbXVsYXRpb24gcnVuIHJlYWNoIGZpbmFsIGVuZHBvaW50PyIpCmlmIChzaW1fZW5kcG9pbnRfbWV0YSR0ID49IHRmKSB7CiAgcHJpbnQoIlllcyIpCn0gZWxzZSB7CiAgcHJpbnQoIk5vIil9CgpgYGAKCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF9tZXRhIDwtIGxpc3QoKQpzaW1fbGlzdF9tZXRhIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgcGF0Y2hQb3BTaXplIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCA3LCByZXBsYWNlID0gVFJVRSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIHgwX21ldGEgPC0gdW5saXN0KGxhcHBseSgKICBzZXFfbGVuKFUpLCAKICBmdW5jdGlvbih4KXsgCiAgICBjKHBhdGNoUG9wU2l6ZVt4XSAtIGluaXRpYWxfaW5mZWN0ZWRbeF0sIGluaXRpYWxfaW5mZWN0ZWRbeF0sIDAsIDAsIHBhdGNoUG9wU2l6ZVt4XSkKICB9CikpCgpuYW1lcyh4MF9tZXRhKSA8LSB1bmxpc3QobGFwcGx5KHNlcV9sZW4oVSksIGZ1bmN0aW9uKHgpIHBhc3RlMChjKCJTIiwiRSIsIkkiLCAiUiIsICJOIiksIHgpKSkKICAKICBvdXRfMTAwX21ldGEgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YSwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhX21ldGEgPC0gb3V0XzEwMF9tZXRhJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFbW2ldXSA8LSBzaW1fZGF0YV9tZXRhCn0KCnNpbV9vdXRwdXRfbWV0YSA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YSkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF9tZXRhIDwtIHNpbV9vdXRwdXRfbWV0YSAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfbWV0YQpgYGAKCgoKYGBge3J9CiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV9tZXRhIDwtIHNpbV9vdXRwdXRfbWV0YSAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLAogICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvMTgwKQpzaW1fc3VtbWFyeV9tZXRhCmBgYAoKIyMjIFZhcnlpbmcgd2FpbmluZyBpbW11bml0eQojIyMjIDAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc19tZXRhXzAgPC0gcGFybXNfbWV0YQpwYXJtc19tZXRhXzAkb21lZ2EgPC0gMAoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0X21ldGFfMCA8LSBzc2EoCiAgeDAgPSB4MF9tZXRhLAogIGEgPSBhX21ldGEsCiAgbnUgPSBudV9tZXRhLAogIHBhcm1zID0gcGFybXNfbWV0YV8wLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhX21ldGFfMCA8LSBvdXRfbWV0YV8wJGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIHNlcGFyYXRlKElELCAKICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF9tZXRhXzAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfbWV0YV8wLCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBmYWNldF93cmFwKH5mYWN0b3IocGF0Y2gsIGxldmVscyA9IHVuaXF1ZShwYXRjaCkpICxuY29sID0gMywgc2NhbGVzID0gImZyZWVfeSIpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfbWV0YV8wCmBgYApgYGB7cn0KIyMgUnVuIG11bHRpcGxlIHNpbXVsYXRpb25zIGFuZCBzYXZpbmcgb3V0cHV0Cm51bV9zaW1zIDwtIDEwMDAKc2ltX2xpc3RfbWV0YV8wIDwtIGxpc3QoKQpzaW1fbGlzdF9tZXRhXzAgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBwYXRjaFBvcFNpemUgPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDcsIHJlcGxhY2UgPSBUUlVFKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgeDBfbWV0YSA8LSB1bmxpc3QoCiAgICAgIGxhcHBseSgKICAgICAgICBzZXFfbGVuKFUpLAogICAgICAgIGZ1bmN0aW9uKHgpewogICAgICAgICAgYyhwYXRjaFBvcFNpemVbeF0gLSBpbml0aWFsX2luZmVjdGVkW3hdLCBpbml0aWFsX2luZmVjdGVkW3hdLCAwLCAwLCBwYXRjaFBvcFNpemVbeF0pCiAgICAgICAgICB9CiAgICAgICAgKSkKCm5hbWVzKHgwX21ldGEpIDwtIHVubGlzdChsYXBwbHkoc2VxX2xlbihVKSwgZnVuY3Rpb24oeCkgcGFzdGUwKGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKSwgeCkpKQoKICBvdXRfMTAwX21ldGFfMCA8LSBzc2EoCiAgICB4MCA9IHgwX21ldGEsCiAgICBhID0gYV9tZXRhLAogICAgbnUgPSBudV9tZXRhLAogICAgcGFybXMgPSBwYXJtc19tZXRhXzAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV9tZXRhXzAgPC0gb3V0XzEwMF9tZXRhXzAkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHNlcGFyYXRlKElELCAKICAgICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3RhdGUsIHZhbHVlc19mcm9tID0gY291bnQpICU+JQogICAgbXV0YXRlKHBlcnNpc3QgPSBjYXNlX3doZW4oSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEkgPT0gMCB+IEYpLAogICAgICAgICAgIHNpbSA9IGkpICU+JQogICAgc2VsZWN0KHNpbSwgcGF0Y2gsIEksIE4sIHBlcnNpc3QpCiAgCiAgc2ltX2xpc3RfbWV0YV8wW1tpXV0gPC0gc2ltX2RhdGFfbWV0YV8wCn0KCnNpbV9vdXRwdXRfbWV0YV8wIDwtIGJpbmRfcm93cyhzaW1fbGlzdF9tZXRhXzApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfbWV0YV8wIDwtIHNpbV9vdXRwdXRfbWV0YV8wICU+JQogIGdyb3VwX2J5KHNpbSkgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX0kgPSBzdW0oSSksIAogICAgICAgICAgICB0b3RhbF9OID0gc3VtKE4pKSAlPiUKICBtdXRhdGUocGVyY2VudF9wZXJzaXN0ID0gdG90YWxfSS8odG90YWxfTikqMTAwLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHRvdGFsX0kgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9JID09IDAgfiBGKSkKc2ltX291dHB1dF9tZXRhXzAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV9tZXRhXzAgPC0gc2ltX291dHB1dF9tZXRhXzAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QsIG5hLnJtID0gVCkvbnVtX3NpbXMpKjEwMCwKICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAwKQpzaW1fc3VtbWFyeV9tZXRhXzAKYGBgCgoKCiMjIyMgMSBEYXkKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfbWV0YV8xIDwtIHBhcm1zX21ldGEKcGFybXNfbWV0YV8xJG9tZWdhIDwtIDEKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF9tZXRhXzEgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGFfMSwKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV9tZXRhXzEgPC0gb3V0X21ldGFfMSRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfbWV0YV8xIDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhX21ldGFfMSwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgZmFjZXRfd3JhcCh+ZmFjdG9yKHBhdGNoLCBsZXZlbHMgPSB1bmlxdWUocGF0Y2gpKSAsbmNvbCA9IDMsIHNjYWxlcyA9ICJmcmVlX3kiKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90X21ldGFfMQpgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0X21ldGFfMSA8LSBsaXN0KCkKc2ltX2xpc3RfbWV0YV8xIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgcGF0Y2hQb3BTaXplIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCA3LCByZXBsYWNlID0gVFJVRSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIHgwX21ldGEgPC0gdW5saXN0KAogICAgICBsYXBwbHkoCiAgICAgICAgc2VxX2xlbihVKSwKICAgICAgICBmdW5jdGlvbih4KXsKICAgICAgICAgIGMocGF0Y2hQb3BTaXplW3hdIC0gaW5pdGlhbF9pbmZlY3RlZFt4XSwgaW5pdGlhbF9pbmZlY3RlZFt4XSwgMCwgMCwgcGF0Y2hQb3BTaXplW3hdKQogICAgICAgICAgfQogICAgICAgICkpCgpuYW1lcyh4MF9tZXRhKSA8LSB1bmxpc3QobGFwcGx5KHNlcV9sZW4oVSksIGZ1bmN0aW9uKHgpIHBhc3RlMChjKCJTIiwiRSIsIkkiLCAiUiIsICJOIiksIHgpKSkKCiAgb3V0XzEwMF9tZXRhXzEgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YV8xLAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfbWV0YV8xIDwtIG91dF8xMDBfbWV0YV8xJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFfMVtbaV1dIDwtIHNpbV9kYXRhX21ldGFfMQp9CgpzaW1fb3V0cHV0X21ldGFfMSA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YV8xKQpgYGAKCmBgYHtyfQojIFN1bW1hcnkgdGFibGUgb2YgZW5kcG9pbnQgZGF0YQpzaW1fb3V0cHV0X21ldGFfMSA8LSBzaW1fb3V0cHV0X21ldGFfMSAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfbWV0YV8xCgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfbWV0YV8xIDwtIHNpbV9vdXRwdXRfbWV0YV8xICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEpCnNpbV9zdW1tYXJ5X21ldGFfMQpgYGAKCgoKCiMjIyMgMyBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zX21ldGFfMyA8LSBwYXJtc19tZXRhCnBhcm1zX21ldGFfMyRvbWVnYSA8LSAxLzMKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF9tZXRhXzMgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGFfMywKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV9tZXRhXzMgPC0gb3V0X21ldGFfMyRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfbWV0YV8zIDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhX21ldGFfMywgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgZmFjZXRfd3JhcCh+ZmFjdG9yKHBhdGNoLCBsZXZlbHMgPSB1bmlxdWUocGF0Y2gpKSAsbmNvbCA9IDMsIHNjYWxlcyA9ICJmcmVlX3kiKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90X21ldGFfMwpgYGAKCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF9tZXRhXzMgPC0gbGlzdCgpCnNpbV9saXN0X21ldGFfMyA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIHBhdGNoUG9wU2l6ZSA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgNywgcmVwbGFjZSA9IFRSVUUpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICB4MF9tZXRhIDwtIHVubGlzdCgKICAgICAgbGFwcGx5KAogICAgICAgIHNlcV9sZW4oVSksCiAgICAgICAgZnVuY3Rpb24oeCl7CiAgICAgICAgICBjKHBhdGNoUG9wU2l6ZVt4XSAtIGluaXRpYWxfaW5mZWN0ZWRbeF0sIGluaXRpYWxfaW5mZWN0ZWRbeF0sIDAsIDAsIHBhdGNoUG9wU2l6ZVt4XSkKICAgICAgICAgIH0KICAgICAgICApKQoKbmFtZXMoeDBfbWV0YSkgPC0gdW5saXN0KGxhcHBseShzZXFfbGVuKFUpLCBmdW5jdGlvbih4KSBwYXN0ZTAoYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpLCB4KSkpCgogIG91dF8xMDBfbWV0YV8zIDwtIHNzYSgKICAgIHgwID0geDBfbWV0YSwKICAgIGEgPSBhX21ldGEsCiAgICBudSA9IG51X21ldGEsCiAgICBwYXJtcyA9IHBhcm1zX21ldGFfMywKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhX21ldGFfMyA8LSBvdXRfMTAwX21ldGFfMyRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBwYXRjaCwgSSwgTiwgcGVyc2lzdCkKICAKICBzaW1fbGlzdF9tZXRhXzNbW2ldXSA8LSBzaW1fZGF0YV9tZXRhXzMKfQoKc2ltX291dHB1dF9tZXRhXzMgPC0gYmluZF9yb3dzKHNpbV9saXN0X21ldGFfMykKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF9tZXRhXzMgPC0gc2ltX291dHB1dF9tZXRhXzMgJT4lCiAgZ3JvdXBfYnkoc2ltKSAlPiUKICBzdW1tYXJpc2UodG90YWxfSSA9IHN1bShJKSwgCiAgICAgICAgICAgIHRvdGFsX04gPSBzdW0oTikpICU+JQogIG11dGF0ZShwZXJjZW50X3BlcnNpc3QgPSB0b3RhbF9JLyh0b3RhbF9OKSoxMDAsCiAgICAgICAgIHBlcnNpc3QgPSBjYXNlX3doZW4odG90YWxfSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsX0kgPT0gMCB+IEYpKQpzaW1fb3V0cHV0X21ldGFfMwoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5X21ldGFfMyA8LSBzaW1fb3V0cHV0X21ldGFfMyAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLCAgICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxLzMpCnNpbV9zdW1tYXJ5X21ldGFfMwpgYGAKCgoKCgoKIyMjIyA3IERheXMKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfbWV0YV83IDwtIHBhcm1zX21ldGEKcGFybXNfbWV0YV83JG9tZWdhIDwtIDEvNwoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0X21ldGFfNyA8LSBzc2EoCiAgeDAgPSB4MF9tZXRhLAogIGEgPSBhX21ldGEsCiAgbnUgPSBudV9tZXRhLAogIHBhcm1zID0gcGFybXNfbWV0YV83LAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhX21ldGFfNyA8LSBvdXRfbWV0YV83JGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIHNlcGFyYXRlKElELCAKICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF9tZXRhXzcgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfbWV0YV83LCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBmYWNldF93cmFwKH5mYWN0b3IocGF0Y2gsIGxldmVscyA9IHVuaXF1ZShwYXRjaCkpICxuY29sID0gMywgc2NhbGVzID0gImZyZWVfeSIpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfbWV0YV83CmBgYAoKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0X21ldGFfNyA8LSBsaXN0KCkKc2ltX2xpc3RfbWV0YV83IDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgcGF0Y2hQb3BTaXplIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCA3LCByZXBsYWNlID0gVFJVRSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIHgwX21ldGEgPC0gdW5saXN0KAogICAgICBsYXBwbHkoCiAgICAgICAgc2VxX2xlbihVKSwKICAgICAgICBmdW5jdGlvbih4KXsKICAgICAgICAgIGMocGF0Y2hQb3BTaXplW3hdIC0gaW5pdGlhbF9pbmZlY3RlZFt4XSwgaW5pdGlhbF9pbmZlY3RlZFt4XSwgMCwgMCwgcGF0Y2hQb3BTaXplW3hdKQogICAgICAgICAgfQogICAgICAgICkpCgpuYW1lcyh4MF9tZXRhKSA8LSB1bmxpc3QobGFwcGx5KHNlcV9sZW4oVSksIGZ1bmN0aW9uKHgpIHBhc3RlMChjKCJTIiwiRSIsIkkiLCAiUiIsICJOIiksIHgpKSkKCiAgb3V0XzEwMF9tZXRhXzcgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YV83LAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfbWV0YV83IDwtIG91dF8xMDBfbWV0YV83JGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFfN1tbaV1dIDwtIHNpbV9kYXRhX21ldGFfNwp9CgpzaW1fb3V0cHV0X21ldGFfNyA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YV83KQpgYGAKCmBgYHtyfQojIFN1bW1hcnkgdGFibGUgb2YgZW5kcG9pbnQgZGF0YQpzaW1fb3V0cHV0X21ldGFfNyA8LSBzaW1fb3V0cHV0X21ldGFfNyAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfbWV0YV83CgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfbWV0YV83IDwtIHNpbV9vdXRwdXRfbWV0YV83ICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvNykKc2ltX3N1bW1hcnlfbWV0YV83CmBgYAoKCgojIyMjIDEwIERheXMKCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zX21ldGFfMTAgPC0gcGFybXNfbWV0YQpwYXJtc19tZXRhXzEwJG9tZWdhIDwtIDEvMTAKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0X21ldGFfMTAgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGFfMTAsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBFeHRyYSBQbG90cwpwbG90X2RhdGFfbWV0YV8xMCA8LSBvdXRfbWV0YV8xMCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfbWV0YV8xMCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV9tZXRhXzEwLCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBmYWNldF93cmFwKH5mYWN0b3IocGF0Y2gsIGxldmVscyA9IHVuaXF1ZShwYXRjaCkpICxuY29sID0gMywgc2NhbGVzID0gImZyZWVfeSIpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfbWV0YV8xMApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0X21ldGFfMTAgPC0gbGlzdCgpCnNpbV9saXN0X21ldGFfMTAgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBwYXRjaFBvcFNpemUgPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDcsIHJlcGxhY2UgPSBUUlVFKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgeDBfbWV0YSA8LSB1bmxpc3QoCiAgICAgIGxhcHBseSgKICAgICAgICBzZXFfbGVuKFUpLAogICAgICAgIGZ1bmN0aW9uKHgpewogICAgICAgICAgYyhwYXRjaFBvcFNpemVbeF0gLSBpbml0aWFsX2luZmVjdGVkW3hdLCBpbml0aWFsX2luZmVjdGVkW3hdLCAwLCAwLCBwYXRjaFBvcFNpemVbeF0pCiAgICAgICAgICB9CiAgICAgICAgKSkKCm5hbWVzKHgwX21ldGEpIDwtIHVubGlzdChsYXBwbHkoc2VxX2xlbihVKSwgZnVuY3Rpb24oeCkgcGFzdGUwKGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKSwgeCkpKQoKICBvdXRfMTAwX21ldGFfMTAgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YV8xMCwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhX21ldGFfMTAgPC0gb3V0XzEwMF9tZXRhXzEwJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFfMTBbW2ldXSA8LSBzaW1fZGF0YV9tZXRhXzEwCn0KCnNpbV9vdXRwdXRfbWV0YV8xMCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YV8xMCkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF9tZXRhXzEwIDwtIHNpbV9vdXRwdXRfbWV0YV8xMCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfbWV0YV8xMCA8LSBzaW1fb3V0cHV0X21ldGFfMTAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QsIG5hLnJtID0gVCkvbnVtX3NpbXMpKjEwMCwgICAgICAgICAgICAgIG1lYW5fcGVyY2VudF9pbmZlY3RlZCA9IG1lYW4ocGVyY2VudF9wZXJzaXN0KSkgJT4lCiAgbXV0YXRlKG9tZWdhID0gMS8xNCkKc2ltX3N1bW1hcnlfbWV0YV8xMApgYGAKCgojIyMjIDIwIERheXMKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfbWV0YV8yMCA8LSBwYXJtc19tZXRhCnBhcm1zX21ldGFfMjAkb21lZ2EgPC0gMS8yMAoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0X21ldGFfMjAgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGFfMjAsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBFeHRyYSBQbG90cwpwbG90X2RhdGFfbWV0YV8yMCA8LSBvdXRfbWV0YV8yMCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfbWV0YV8yMCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV9tZXRhXzIwLCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBmYWNldF93cmFwKH5mYWN0b3IocGF0Y2gsIGxldmVscyA9IHVuaXF1ZShwYXRjaCkpICxuY29sID0gMywgc2NhbGVzID0gImZyZWVfeSIpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfbWV0YV8yMApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0X21ldGFfMjAgPC0gbGlzdCgpCnNpbV9saXN0X21ldGFfMjAgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBwYXRjaFBvcFNpemUgPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDcsIHJlcGxhY2UgPSBUUlVFKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgeDBfbWV0YSA8LSB1bmxpc3QoCiAgICAgIGxhcHBseSgKICAgICAgICBzZXFfbGVuKFUpLAogICAgICAgIGZ1bmN0aW9uKHgpewogICAgICAgICAgYyhwYXRjaFBvcFNpemVbeF0gLSBpbml0aWFsX2luZmVjdGVkW3hdLCBpbml0aWFsX2luZmVjdGVkW3hdLCAwLCAwLCBwYXRjaFBvcFNpemVbeF0pCiAgICAgICAgICB9CiAgICAgICAgKSkKCm5hbWVzKHgwX21ldGEpIDwtIHVubGlzdChsYXBwbHkoc2VxX2xlbihVKSwgZnVuY3Rpb24oeCkgcGFzdGUwKGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKSwgeCkpKQoKICBvdXRfMTAwX21ldGFfMjAgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YV8yMCwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhX21ldGFfMjAgPC0gb3V0XzEwMF9tZXRhXzIwJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFfMjBbW2ldXSA8LSBzaW1fZGF0YV9tZXRhXzIwCn0KCnNpbV9vdXRwdXRfbWV0YV8yMCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YV8yMCkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF9tZXRhXzIwIDwtIHNpbV9vdXRwdXRfbWV0YV8yMCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfbWV0YV8yMAoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5X21ldGFfMjAgPC0gc2ltX291dHB1dF9tZXRhXzIwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvMjApCnNpbV9zdW1tYXJ5X21ldGFfMjAKYGBgCgoKCgoKCiMjIyMgMzAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc19tZXRhXzMwIDwtIHBhcm1zX21ldGEKcGFybXNfbWV0YV8zMCRvbWVnYSA8LSAxLzMwCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfbWV0YV8zMCA8LSBzc2EoCiAgeDAgPSB4MF9tZXRhLAogIGEgPSBhX21ldGEsCiAgbnUgPSBudV9tZXRhLAogIHBhcm1zID0gcGFybXNfbWV0YV8zMCwKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV9tZXRhXzMwIDwtIG91dF9tZXRhXzMwJGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIHNlcGFyYXRlKElELCAKICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF9tZXRhXzMwIDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhX21ldGFfMzAsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGZhY2V0X3dyYXAofmZhY3RvcihwYXRjaCwgbGV2ZWxzID0gdW5pcXVlKHBhdGNoKSkgLG5jb2wgPSAzLCBzY2FsZXMgPSAiZnJlZV95IikrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF9tZXRhXzMwCmBgYApgYGB7cn0KIyMgUnVuIG11bHRpcGxlIHNpbXVsYXRpb25zIGFuZCBzYXZpbmcgb3V0cHV0Cm51bV9zaW1zIDwtIDEwMDAKc2ltX2xpc3RfbWV0YV8zMCA8LSBsaXN0KCkKc2ltX2xpc3RfbWV0YV8zMCA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIHBhdGNoUG9wU2l6ZSA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgNywgcmVwbGFjZSA9IFRSVUUpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICB4MF9tZXRhIDwtIHVubGlzdCgKICAgICAgbGFwcGx5KAogICAgICAgIHNlcV9sZW4oVSksCiAgICAgICAgZnVuY3Rpb24oeCl7CiAgICAgICAgICBjKHBhdGNoUG9wU2l6ZVt4XSAtIGluaXRpYWxfaW5mZWN0ZWRbeF0sIGluaXRpYWxfaW5mZWN0ZWRbeF0sIDAsIDAsIHBhdGNoUG9wU2l6ZVt4XSkKICAgICAgICAgIH0KICAgICAgICApKQoKbmFtZXMoeDBfbWV0YSkgPC0gdW5saXN0KGxhcHBseShzZXFfbGVuKFUpLCBmdW5jdGlvbih4KSBwYXN0ZTAoYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpLCB4KSkpCgogIG91dF8xMDBfbWV0YV8zMCA8LSBzc2EoCiAgICB4MCA9IHgwX21ldGEsCiAgICBhID0gYV9tZXRhLAogICAgbnUgPSBudV9tZXRhLAogICAgcGFybXMgPSBwYXJtc19tZXRhXzMwLAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfbWV0YV8zMCA8LSBvdXRfMTAwX21ldGFfMzAkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHNlcGFyYXRlKElELCAKICAgICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3RhdGUsIHZhbHVlc19mcm9tID0gY291bnQpICU+JQogICAgbXV0YXRlKHBlcnNpc3QgPSBjYXNlX3doZW4oSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEkgPT0gMCB+IEYpLAogICAgICAgICAgIHNpbSA9IGkpICU+JQogICAgc2VsZWN0KHNpbSwgcGF0Y2gsIEksIE4sIHBlcnNpc3QpCiAgCiAgc2ltX2xpc3RfbWV0YV8zMFtbaV1dIDwtIHNpbV9kYXRhX21ldGFfMzAKfQoKc2ltX291dHB1dF9tZXRhXzMwIDwtIGJpbmRfcm93cyhzaW1fbGlzdF9tZXRhXzMwKQpgYGAKCmBgYHtyfQojIFN1bW1hcnkgdGFibGUgb2YgZW5kcG9pbnQgZGF0YQpzaW1fb3V0cHV0X21ldGFfMzAgPC0gc2ltX291dHB1dF9tZXRhXzMwICU+JQogIGdyb3VwX2J5KHNpbSkgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX0kgPSBzdW0oSSksIAogICAgICAgICAgICB0b3RhbF9OID0gc3VtKE4pKSAlPiUKICBtdXRhdGUocGVyY2VudF9wZXJzaXN0ID0gdG90YWxfSS8odG90YWxfTikqMTAwLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHRvdGFsX0kgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9JID09IDAgfiBGKSkKc2ltX291dHB1dF9tZXRhXzMwCgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfbWV0YV8zMCA8LSBzaW1fb3V0cHV0X21ldGFfMzAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QsIG5hLnJtID0gVCkvbnVtX3NpbXMpKjEwMCwKICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxLzMwKQpzaW1fc3VtbWFyeV9tZXRhXzMwCmBgYAoKCgojIyMjIDQwIERheXMKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfbWV0YV80MCA8LSBwYXJtc19tZXRhCnBhcm1zX21ldGFfNDAkb21lZ2EgPC0gMS80MAoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0X21ldGFfNDAgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGFfNDAsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBFeHRyYSBQbG90cwpwbG90X2RhdGFfbWV0YV80MCA8LSBvdXRfbWV0YV80MCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfbWV0YV80MCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV9tZXRhXzQwLCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBmYWNldF93cmFwKH5mYWN0b3IocGF0Y2gsIGxldmVscyA9IHVuaXF1ZShwYXRjaCkpICxuY29sID0gMywgc2NhbGVzID0gImZyZWVfeSIpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfbWV0YV80MApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0X21ldGFfNDAgPC0gbGlzdCgpCnNpbV9saXN0X21ldGFfNDAgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBwYXRjaFBvcFNpemUgPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDcsIHJlcGxhY2UgPSBUUlVFKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgeDBfbWV0YSA8LSB1bmxpc3QoCiAgICAgIGxhcHBseSgKICAgICAgICBzZXFfbGVuKFUpLAogICAgICAgIGZ1bmN0aW9uKHgpewogICAgICAgICAgYyhwYXRjaFBvcFNpemVbeF0gLSBpbml0aWFsX2luZmVjdGVkW3hdLCBpbml0aWFsX2luZmVjdGVkW3hdLCAwLCAwLCBwYXRjaFBvcFNpemVbeF0pCiAgICAgICAgICB9CiAgICAgICAgKSkKCm5hbWVzKHgwX21ldGEpIDwtIHVubGlzdChsYXBwbHkoc2VxX2xlbihVKSwgZnVuY3Rpb24oeCkgcGFzdGUwKGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKSwgeCkpKQoKICBvdXRfMTAwX21ldGFfNDAgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YV80MCwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhX21ldGFfNDAgPC0gb3V0XzEwMF9tZXRhXzQwJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFfNDBbW2ldXSA8LSBzaW1fZGF0YV9tZXRhXzQwCn0KCnNpbV9vdXRwdXRfbWV0YV80MCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YV80MCkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF9tZXRhXzQwIDwtIHNpbV9vdXRwdXRfbWV0YV80MCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfbWV0YV80MAoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5X21ldGFfNDAgPC0gc2ltX291dHB1dF9tZXRhXzQwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvNDApCnNpbV9zdW1tYXJ5X21ldGFfNDAKYGBgCgoKCgoKCgojIyMjIDUwIERheXMKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfbWV0YV81MCA8LSBwYXJtc19tZXRhCnBhcm1zX21ldGFfNTAkb21lZ2EgPC0gMS81MAoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0X21ldGFfNTAgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGFfNTAsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBFeHRyYSBQbG90cwpwbG90X2RhdGFfbWV0YV81MCA8LSBvdXRfbWV0YV81MCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfbWV0YV81MCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV9tZXRhXzUwLCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBmYWNldF93cmFwKH5mYWN0b3IocGF0Y2gsIGxldmVscyA9IHVuaXF1ZShwYXRjaCkpICxuY29sID0gMywgc2NhbGVzID0gImZyZWVfeSIpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfbWV0YV81MApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0X21ldGFfNTAgPC0gbGlzdCgpCnNpbV9saXN0X21ldGFfNTAgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBwYXRjaFBvcFNpemUgPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDcsIHJlcGxhY2UgPSBUUlVFKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgeDBfbWV0YSA8LSB1bmxpc3QoCiAgICAgIGxhcHBseSgKICAgICAgICBzZXFfbGVuKFUpLAogICAgICAgIGZ1bmN0aW9uKHgpewogICAgICAgICAgYyhwYXRjaFBvcFNpemVbeF0gLSBpbml0aWFsX2luZmVjdGVkW3hdLCBpbml0aWFsX2luZmVjdGVkW3hdLCAwLCAwLCBwYXRjaFBvcFNpemVbeF0pCiAgICAgICAgICB9CiAgICAgICAgKSkKCm5hbWVzKHgwX21ldGEpIDwtIHVubGlzdChsYXBwbHkoc2VxX2xlbihVKSwgZnVuY3Rpb24oeCkgcGFzdGUwKGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKSwgeCkpKQoKICBvdXRfMTAwX21ldGFfNTAgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YV81MCwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhX21ldGFfNTAgPC0gb3V0XzEwMF9tZXRhXzUwJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFfNTBbW2ldXSA8LSBzaW1fZGF0YV9tZXRhXzUwCn0KCnNpbV9vdXRwdXRfbWV0YV81MCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YV81MCkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF9tZXRhXzUwIDwtIHNpbV9vdXRwdXRfbWV0YV81MCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfbWV0YV81MAoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5X21ldGFfNTAgPC0gc2ltX291dHB1dF9tZXRhXzUwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvNTApCnNpbV9zdW1tYXJ5X21ldGFfNTAKYGBgCgoKCgoKIyMjIyA2MCBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zX21ldGFfNjAgPC0gcGFybXNfbWV0YQpwYXJtc19tZXRhXzYwJG9tZWdhIDwtIDEvNjAKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF9tZXRhXzYwIDwtIHNzYSgKICB4MCA9IHgwX21ldGEsCiAgYSA9IGFfbWV0YSwKICBudSA9IG51X21ldGEsCiAgcGFybXMgPSBwYXJtc19tZXRhXzYwLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhX21ldGFfNjAgPC0gb3V0X21ldGFfNjAkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogIG11dGF0ZShzdGF0ZSA9IGZhY3RvcihzdGF0ZSwgbGV2ZWxzID0gYygiUyIsICJFIiwgIkkiLCAiUiIsICJOIikpKSAjJT4lCiAgI2ZpbHRlcihzdGF0ZSAhPSAiTiIpCgpwbG90X21ldGFfNjAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfbWV0YV82MCwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgZmFjZXRfd3JhcCh+ZmFjdG9yKHBhdGNoLCBsZXZlbHMgPSB1bmlxdWUocGF0Y2gpKSAsbmNvbCA9IDMsIHNjYWxlcyA9ICJmcmVlX3kiKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90X21ldGFfNjAKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF9tZXRhXzYwIDwtIGxpc3QoKQpzaW1fbGlzdF9tZXRhXzYwIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgcGF0Y2hQb3BTaXplIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCA3LCByZXBsYWNlID0gVFJVRSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIHgwX21ldGEgPC0gdW5saXN0KAogICAgICBsYXBwbHkoCiAgICAgICAgc2VxX2xlbihVKSwKICAgICAgICBmdW5jdGlvbih4KXsKICAgICAgICAgIGMocGF0Y2hQb3BTaXplW3hdIC0gaW5pdGlhbF9pbmZlY3RlZFt4XSwgaW5pdGlhbF9pbmZlY3RlZFt4XSwgMCwgMCwgcGF0Y2hQb3BTaXplW3hdKQogICAgICAgICAgfQogICAgICAgICkpCgpuYW1lcyh4MF9tZXRhKSA8LSB1bmxpc3QobGFwcGx5KHNlcV9sZW4oVSksIGZ1bmN0aW9uKHgpIHBhc3RlMChjKCJTIiwiRSIsIkkiLCAiUiIsICJOIiksIHgpKSkKCiAgb3V0XzEwMF9tZXRhXzYwIDwtIHNzYSgKICAgIHgwID0geDBfbWV0YSwKICAgIGEgPSBhX21ldGEsCiAgICBudSA9IG51X21ldGEsCiAgICBwYXJtcyA9IHBhcm1zX21ldGFfNjAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV9tZXRhXzYwIDwtIG91dF8xMDBfbWV0YV82MCRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBwYXRjaCwgSSwgTiwgcGVyc2lzdCkKICAKICBzaW1fbGlzdF9tZXRhXzYwW1tpXV0gPC0gc2ltX2RhdGFfbWV0YV82MAp9CgpzaW1fb3V0cHV0X21ldGFfNjAgPC0gYmluZF9yb3dzKHNpbV9saXN0X21ldGFfNjApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfbWV0YV82MCA8LSBzaW1fb3V0cHV0X21ldGFfNjAgJT4lCiAgZ3JvdXBfYnkoc2ltKSAlPiUKICBzdW1tYXJpc2UodG90YWxfSSA9IHN1bShJKSwgCiAgICAgICAgICAgIHRvdGFsX04gPSBzdW0oTikpICU+JQogIG11dGF0ZShwZXJjZW50X3BlcnNpc3QgPSB0b3RhbF9JLyh0b3RhbF9OKSoxMDAsCiAgICAgICAgIHBlcnNpc3QgPSBjYXNlX3doZW4odG90YWxfSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsX0kgPT0gMCB+IEYpKQpzaW1fb3V0cHV0X21ldGFfNjAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV9tZXRhXzYwIDwtIHNpbV9vdXRwdXRfbWV0YV82MCAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLCAgICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxLzYwKQpzaW1fc3VtbWFyeV9tZXRhXzYwCmBgYAoKCgoKIyMjIyA3MCBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zX21ldGFfNzAgPC0gcGFybXNfbWV0YQpwYXJtc19tZXRhXzcwJG9tZWdhIDwtIDEvNzAKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF9tZXRhXzcwIDwtIHNzYSgKICB4MCA9IHgwX21ldGEsCiAgYSA9IGFfbWV0YSwKICBudSA9IG51X21ldGEsCiAgcGFybXMgPSBwYXJtc19tZXRhXzcwLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhX21ldGFfNzAgPC0gb3V0X21ldGFfNzAkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogIG11dGF0ZShzdGF0ZSA9IGZhY3RvcihzdGF0ZSwgbGV2ZWxzID0gYygiUyIsICJFIiwgIkkiLCAiUiIsICJOIikpKSAjJT4lCiAgI2ZpbHRlcihzdGF0ZSAhPSAiTiIpCgpwbG90X21ldGFfNzAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfbWV0YV83MCwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgZmFjZXRfd3JhcCh+ZmFjdG9yKHBhdGNoLCBsZXZlbHMgPSB1bmlxdWUocGF0Y2gpKSAsbmNvbCA9IDMsIHNjYWxlcyA9ICJmcmVlX3kiKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90X21ldGFfNzAKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF9tZXRhXzcwIDwtIGxpc3QoKQpzaW1fbGlzdF9tZXRhXzcwIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgcGF0Y2hQb3BTaXplIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCA3LCByZXBsYWNlID0gVFJVRSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIHgwX21ldGEgPC0gdW5saXN0KAogICAgICBsYXBwbHkoCiAgICAgICAgc2VxX2xlbihVKSwKICAgICAgICBmdW5jdGlvbih4KXsKICAgICAgICAgIGMocGF0Y2hQb3BTaXplW3hdIC0gaW5pdGlhbF9pbmZlY3RlZFt4XSwgaW5pdGlhbF9pbmZlY3RlZFt4XSwgMCwgMCwgcGF0Y2hQb3BTaXplW3hdKQogICAgICAgICAgfQogICAgICAgICkpCgpuYW1lcyh4MF9tZXRhKSA8LSB1bmxpc3QobGFwcGx5KHNlcV9sZW4oVSksIGZ1bmN0aW9uKHgpIHBhc3RlMChjKCJTIiwiRSIsIkkiLCAiUiIsICJOIiksIHgpKSkKCiAgb3V0XzEwMF9tZXRhXzcwIDwtIHNzYSgKICAgIHgwID0geDBfbWV0YSwKICAgIGEgPSBhX21ldGEsCiAgICBudSA9IG51X21ldGEsCiAgICBwYXJtcyA9IHBhcm1zX21ldGFfNzAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV9tZXRhXzcwIDwtIG91dF8xMDBfbWV0YV83MCRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBwYXRjaCwgSSwgTiwgcGVyc2lzdCkKICAKICBzaW1fbGlzdF9tZXRhXzcwW1tpXV0gPC0gc2ltX2RhdGFfbWV0YV83MAp9CgpzaW1fb3V0cHV0X21ldGFfNzAgPC0gYmluZF9yb3dzKHNpbV9saXN0X21ldGFfNzApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfbWV0YV83MCA8LSBzaW1fb3V0cHV0X21ldGFfNzAgJT4lCiAgZ3JvdXBfYnkoc2ltKSAlPiUKICBzdW1tYXJpc2UodG90YWxfSSA9IHN1bShJKSwgCiAgICAgICAgICAgIHRvdGFsX04gPSBzdW0oTikpICU+JQogIG11dGF0ZShwZXJjZW50X3BlcnNpc3QgPSB0b3RhbF9JLyh0b3RhbF9OKSoxMDAsCiAgICAgICAgIHBlcnNpc3QgPSBjYXNlX3doZW4odG90YWxfSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsX0kgPT0gMCB+IEYpKQpzaW1fb3V0cHV0X21ldGFfNzAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV9tZXRhXzcwIDwtIHNpbV9vdXRwdXRfbWV0YV83MCAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLCAgICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxLzcwKQpzaW1fc3VtbWFyeV9tZXRhXzcwCmBgYAoKCiMjIyMgODAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc19tZXRhXzgwIDwtIHBhcm1zX21ldGEKcGFybXNfbWV0YV84MCRvbWVnYSA8LSAxLzgwCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfbWV0YV84MCA8LSBzc2EoCiAgeDAgPSB4MF9tZXRhLAogIGEgPSBhX21ldGEsCiAgbnUgPSBudV9tZXRhLAogIHBhcm1zID0gcGFybXNfbWV0YV84MCwKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV9tZXRhXzgwIDwtIG91dF9tZXRhXzgwJGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIHNlcGFyYXRlKElELCAKICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF9tZXRhXzgwIDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhX21ldGFfODAsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGZhY2V0X3dyYXAofmZhY3RvcihwYXRjaCwgbGV2ZWxzID0gdW5pcXVlKHBhdGNoKSkgLG5jb2wgPSAzLCBzY2FsZXMgPSAiZnJlZV95IikrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF9tZXRhXzgwCmBgYApgYGB7cn0KIyMgUnVuIG11bHRpcGxlIHNpbXVsYXRpb25zIGFuZCBzYXZpbmcgb3V0cHV0Cm51bV9zaW1zIDwtIDEwMDAKc2ltX2xpc3RfbWV0YV84MCA8LSBsaXN0KCkKc2ltX2xpc3RfbWV0YV84MCA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIHBhdGNoUG9wU2l6ZSA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgNywgcmVwbGFjZSA9IFRSVUUpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICB4MF9tZXRhIDwtIHVubGlzdCgKICAgICAgbGFwcGx5KAogICAgICAgIHNlcV9sZW4oVSksCiAgICAgICAgZnVuY3Rpb24oeCl7CiAgICAgICAgICBjKHBhdGNoUG9wU2l6ZVt4XSAtIGluaXRpYWxfaW5mZWN0ZWRbeF0sIGluaXRpYWxfaW5mZWN0ZWRbeF0sIDAsIDAsIHBhdGNoUG9wU2l6ZVt4XSkKICAgICAgICAgIH0KICAgICAgICApKQoKbmFtZXMoeDBfbWV0YSkgPC0gdW5saXN0KGxhcHBseShzZXFfbGVuKFUpLCBmdW5jdGlvbih4KSBwYXN0ZTAoYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpLCB4KSkpCgogIG91dF8xMDBfbWV0YV84MCA8LSBzc2EoCiAgICB4MCA9IHgwX21ldGEsCiAgICBhID0gYV9tZXRhLAogICAgbnUgPSBudV9tZXRhLAogICAgcGFybXMgPSBwYXJtc19tZXRhXzgwLAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfbWV0YV84MCA8LSBvdXRfMTAwX21ldGFfODAkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHNlcGFyYXRlKElELCAKICAgICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3RhdGUsIHZhbHVlc19mcm9tID0gY291bnQpICU+JQogICAgbXV0YXRlKHBlcnNpc3QgPSBjYXNlX3doZW4oSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEkgPT0gMCB+IEYpLAogICAgICAgICAgIHNpbSA9IGkpICU+JQogICAgc2VsZWN0KHNpbSwgcGF0Y2gsIEksIE4sIHBlcnNpc3QpCiAgCiAgc2ltX2xpc3RfbWV0YV84MFtbaV1dIDwtIHNpbV9kYXRhX21ldGFfODAKfQoKc2ltX291dHB1dF9tZXRhXzgwIDwtIGJpbmRfcm93cyhzaW1fbGlzdF9tZXRhXzgwKQpgYGAKCmBgYHtyfQojIFN1bW1hcnkgdGFibGUgb2YgZW5kcG9pbnQgZGF0YQpzaW1fb3V0cHV0X21ldGFfODAgPC0gc2ltX291dHB1dF9tZXRhXzgwICU+JQogIGdyb3VwX2J5KHNpbSkgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX0kgPSBzdW0oSSksIAogICAgICAgICAgICB0b3RhbF9OID0gc3VtKE4pKSAlPiUKICBtdXRhdGUocGVyY2VudF9wZXJzaXN0ID0gdG90YWxfSS8odG90YWxfTikqMTAwLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHRvdGFsX0kgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9JID09IDAgfiBGKSkKc2ltX291dHB1dF9tZXRhXzgwCgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfbWV0YV84MCA8LSBzaW1fb3V0cHV0X21ldGFfODAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QsIG5hLnJtID0gVCkvbnVtX3NpbXMpKjEwMCwgICAgICAgICAgICAgIG1lYW5fcGVyY2VudF9pbmZlY3RlZCA9IG1lYW4ocGVyY2VudF9wZXJzaXN0KSkgJT4lCiAgbXV0YXRlKG9tZWdhID0gMS84MCkKc2ltX3N1bW1hcnlfbWV0YV84MApgYGAKCgoKIyMjIyA5MCBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zX21ldGFfOTAgPC0gcGFybXNfbWV0YQpwYXJtc19tZXRhXzkwJG9tZWdhIDwtIDEvOTAKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF9tZXRhXzkwIDwtIHNzYSgKICB4MCA9IHgwX21ldGEsCiAgYSA9IGFfbWV0YSwKICBudSA9IG51X21ldGEsCiAgcGFybXMgPSBwYXJtc19tZXRhXzkwLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhX21ldGFfOTAgPC0gb3V0X21ldGFfOTAkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogIG11dGF0ZShzdGF0ZSA9IGZhY3RvcihzdGF0ZSwgbGV2ZWxzID0gYygiUyIsICJFIiwgIkkiLCAiUiIsICJOIikpKSAjJT4lCiAgI2ZpbHRlcihzdGF0ZSAhPSAiTiIpCgpwbG90X21ldGFfOTAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfbWV0YV85MCwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgZmFjZXRfd3JhcCh+ZmFjdG9yKHBhdGNoLCBsZXZlbHMgPSB1bmlxdWUocGF0Y2gpKSAsbmNvbCA9IDMsIHNjYWxlcyA9ICJmcmVlX3kiKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90X21ldGFfOTAKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF9tZXRhXzkwIDwtIGxpc3QoKQpzaW1fbGlzdF9tZXRhXzkwIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgcGF0Y2hQb3BTaXplIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCA3LCByZXBsYWNlID0gVFJVRSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIHgwX21ldGEgPC0gdW5saXN0KAogICAgICBsYXBwbHkoCiAgICAgICAgc2VxX2xlbihVKSwKICAgICAgICBmdW5jdGlvbih4KXsKICAgICAgICAgIGMocGF0Y2hQb3BTaXplW3hdIC0gaW5pdGlhbF9pbmZlY3RlZFt4XSwgaW5pdGlhbF9pbmZlY3RlZFt4XSwgMCwgMCwgcGF0Y2hQb3BTaXplW3hdKQogICAgICAgICAgfQogICAgICAgICkpCgpuYW1lcyh4MF9tZXRhKSA8LSB1bmxpc3QobGFwcGx5KHNlcV9sZW4oVSksIGZ1bmN0aW9uKHgpIHBhc3RlMChjKCJTIiwiRSIsIkkiLCAiUiIsICJOIiksIHgpKSkKCiAgb3V0XzEwMF9tZXRhXzkwIDwtIHNzYSgKICAgIHgwID0geDBfbWV0YSwKICAgIGEgPSBhX21ldGEsCiAgICBudSA9IG51X21ldGEsCiAgICBwYXJtcyA9IHBhcm1zX21ldGFfOTAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV9tZXRhXzkwIDwtIG91dF8xMDBfbWV0YV85MCRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBwYXRjaCwgSSwgTiwgcGVyc2lzdCkKICAKICBzaW1fbGlzdF9tZXRhXzkwW1tpXV0gPC0gc2ltX2RhdGFfbWV0YV85MAp9CgpzaW1fb3V0cHV0X21ldGFfOTAgPC0gYmluZF9yb3dzKHNpbV9saXN0X21ldGFfOTApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfbWV0YV85MCA8LSBzaW1fb3V0cHV0X21ldGFfOTAgJT4lCiAgZ3JvdXBfYnkoc2ltKSAlPiUKICBzdW1tYXJpc2UodG90YWxfSSA9IHN1bShJKSwgCiAgICAgICAgICAgIHRvdGFsX04gPSBzdW0oTikpICU+JQogIG11dGF0ZShwZXJjZW50X3BlcnNpc3QgPSB0b3RhbF9JLyh0b3RhbF9OKSoxMDAsCiAgICAgICAgIHBlcnNpc3QgPSBjYXNlX3doZW4odG90YWxfSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsX0kgPT0gMCB+IEYpKQpzaW1fb3V0cHV0X21ldGFfOTAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV9tZXRhXzkwIDwtIHNpbV9vdXRwdXRfbWV0YV85MCAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLCAgICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxLzkwKQpzaW1fc3VtbWFyeV9tZXRhXzkwCmBgYAoKCgoKCgoKIyMjIyAxMDAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc19tZXRhXzEwMCA8LSBwYXJtc19tZXRhCnBhcm1zX21ldGFfMTAwJG9tZWdhIDwtIDEvMTAwCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfbWV0YV8xMDAgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGFfMTAwLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhX21ldGFfMTAwIDwtIG91dF9tZXRhXzEwMCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfbWV0YV8xMDAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfbWV0YV8xMDAsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGZhY2V0X3dyYXAofmZhY3RvcihwYXRjaCwgbGV2ZWxzID0gdW5pcXVlKHBhdGNoKSkgLG5jb2wgPSAzLCBzY2FsZXMgPSAiZnJlZV95IikrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF9tZXRhXzEwMApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0X21ldGFfMTAwIDwtIGxpc3QoKQpzaW1fbGlzdF9tZXRhXzEwMCA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIHBhdGNoUG9wU2l6ZSA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgNywgcmVwbGFjZSA9IFRSVUUpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICB4MF9tZXRhIDwtIHVubGlzdCgKICAgICAgbGFwcGx5KAogICAgICAgIHNlcV9sZW4oVSksCiAgICAgICAgZnVuY3Rpb24oeCl7CiAgICAgICAgICBjKHBhdGNoUG9wU2l6ZVt4XSAtIGluaXRpYWxfaW5mZWN0ZWRbeF0sIGluaXRpYWxfaW5mZWN0ZWRbeF0sIDAsIDAsIHBhdGNoUG9wU2l6ZVt4XSkKICAgICAgICAgIH0KICAgICAgICApKQoKbmFtZXMoeDBfbWV0YSkgPC0gdW5saXN0KGxhcHBseShzZXFfbGVuKFUpLCBmdW5jdGlvbih4KSBwYXN0ZTAoYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpLCB4KSkpCgogIG91dF8xMDBfbWV0YV8xMDAgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YV8xMDAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV9tZXRhXzEwMCA8LSBvdXRfMTAwX21ldGFfMTAwJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFfMTAwW1tpXV0gPC0gc2ltX2RhdGFfbWV0YV8xMDAKfQoKc2ltX291dHB1dF9tZXRhXzEwMCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YV8xMDApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfbWV0YV8xMDAgPC0gc2ltX291dHB1dF9tZXRhXzEwMCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfbWV0YV8xMDAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV9tZXRhXzEwMCA8LSBzaW1fb3V0cHV0X21ldGFfMTAwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvMTAwKQpzaW1fc3VtbWFyeV9tZXRhXzEwMApgYGAKCiMjIyMgMTEwIERheXMKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfbWV0YV8xMTAgPC0gcGFybXNfbWV0YQpwYXJtc19tZXRhXzExMCRvbWVnYSA8LSAxLzExMAoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0X21ldGFfMTEwIDwtIHNzYSgKICB4MCA9IHgwX21ldGEsCiAgYSA9IGFfbWV0YSwKICBudSA9IG51X21ldGEsCiAgcGFybXMgPSBwYXJtc19tZXRhXzExMCwKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV9tZXRhXzExMCA8LSBvdXRfbWV0YV8xMTAkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogIG11dGF0ZShzdGF0ZSA9IGZhY3RvcihzdGF0ZSwgbGV2ZWxzID0gYygiUyIsICJFIiwgIkkiLCAiUiIsICJOIikpKSAjJT4lCiAgI2ZpbHRlcihzdGF0ZSAhPSAiTiIpCgpwbG90X21ldGFfMTEwIDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhX21ldGFfMTEwLCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBmYWNldF93cmFwKH5mYWN0b3IocGF0Y2gsIGxldmVscyA9IHVuaXF1ZShwYXRjaCkpICxuY29sID0gMywgc2NhbGVzID0gImZyZWVfeSIpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfbWV0YV8xMTAKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF9tZXRhXzExMCA8LSBsaXN0KCkKc2ltX2xpc3RfbWV0YV8xMTAgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBwYXRjaFBvcFNpemUgPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDcsIHJlcGxhY2UgPSBUUlVFKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgeDBfbWV0YSA8LSB1bmxpc3QoCiAgICAgIGxhcHBseSgKICAgICAgICBzZXFfbGVuKFUpLAogICAgICAgIGZ1bmN0aW9uKHgpewogICAgICAgICAgYyhwYXRjaFBvcFNpemVbeF0gLSBpbml0aWFsX2luZmVjdGVkW3hdLCBpbml0aWFsX2luZmVjdGVkW3hdLCAwLCAwLCBwYXRjaFBvcFNpemVbeF0pCiAgICAgICAgICB9CiAgICAgICAgKSkKCm5hbWVzKHgwX21ldGEpIDwtIHVubGlzdChsYXBwbHkoc2VxX2xlbihVKSwgZnVuY3Rpb24oeCkgcGFzdGUwKGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKSwgeCkpKQoKICBvdXRfMTAwX21ldGFfMTEwIDwtIHNzYSgKICAgIHgwID0geDBfbWV0YSwKICAgIGEgPSBhX21ldGEsCiAgICBudSA9IG51X21ldGEsCiAgICBwYXJtcyA9IHBhcm1zX21ldGFfMTEwLAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfbWV0YV8xMTAgPC0gb3V0XzEwMF9tZXRhXzExMCRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBwYXRjaCwgSSwgTiwgcGVyc2lzdCkKICAKICBzaW1fbGlzdF9tZXRhXzExMFtbaV1dIDwtIHNpbV9kYXRhX21ldGFfMTEwCn0KCnNpbV9vdXRwdXRfbWV0YV8xMTAgPC0gYmluZF9yb3dzKHNpbV9saXN0X21ldGFfMTEwKQpgYGAKCmBgYHtyfQojIFN1bW1hcnkgdGFibGUgb2YgZW5kcG9pbnQgZGF0YQpzaW1fb3V0cHV0X21ldGFfMTEwIDwtIHNpbV9vdXRwdXRfbWV0YV8xMTAgJT4lCiAgZ3JvdXBfYnkoc2ltKSAlPiUKICBzdW1tYXJpc2UodG90YWxfSSA9IHN1bShJKSwgCiAgICAgICAgICAgIHRvdGFsX04gPSBzdW0oTikpICU+JQogIG11dGF0ZShwZXJjZW50X3BlcnNpc3QgPSB0b3RhbF9JLyh0b3RhbF9OKSoxMDAsCiAgICAgICAgIHBlcnNpc3QgPSBjYXNlX3doZW4odG90YWxfSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsX0kgPT0gMCB+IEYpKQpzaW1fb3V0cHV0X21ldGFfMTEwCgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfbWV0YV8xMTAgPC0gc2ltX291dHB1dF9tZXRhXzExMCAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLCAgICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxLzExMCkKc2ltX3N1bW1hcnlfbWV0YV8xMTAKYGBgCgojIyMjIDEyMCBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zX21ldGFfMTIwIDwtIHBhcm1zX21ldGEKcGFybXNfbWV0YV8xMjAkb21lZ2EgPC0gMS8xMjAKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF9tZXRhXzEyMCA8LSBzc2EoCiAgeDAgPSB4MF9tZXRhLAogIGEgPSBhX21ldGEsCiAgbnUgPSBudV9tZXRhLAogIHBhcm1zID0gcGFybXNfbWV0YV8xMjAsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBFeHRyYSBQbG90cwpwbG90X2RhdGFfbWV0YV8xMjAgPC0gb3V0X21ldGFfMTIwJGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIHNlcGFyYXRlKElELCAKICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF9tZXRhXzEyMCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV9tZXRhXzEyMCwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgZmFjZXRfd3JhcCh+ZmFjdG9yKHBhdGNoLCBsZXZlbHMgPSB1bmlxdWUocGF0Y2gpKSAsbmNvbCA9IDMsIHNjYWxlcyA9ICJmcmVlX3kiKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90X21ldGFfMTIwCmBgYApgYGB7cn0KIyMgUnVuIG11bHRpcGxlIHNpbXVsYXRpb25zIGFuZCBzYXZpbmcgb3V0cHV0Cm51bV9zaW1zIDwtIDEwMDAKc2ltX2xpc3RfbWV0YV8xMjAgPC0gbGlzdCgpCnNpbV9saXN0X21ldGFfMTIwIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgcGF0Y2hQb3BTaXplIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCA3LCByZXBsYWNlID0gVFJVRSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIHgwX21ldGEgPC0gdW5saXN0KAogICAgICBsYXBwbHkoCiAgICAgICAgc2VxX2xlbihVKSwKICAgICAgICBmdW5jdGlvbih4KXsKICAgICAgICAgIGMocGF0Y2hQb3BTaXplW3hdIC0gaW5pdGlhbF9pbmZlY3RlZFt4XSwgaW5pdGlhbF9pbmZlY3RlZFt4XSwgMCwgMCwgcGF0Y2hQb3BTaXplW3hdKQogICAgICAgICAgfQogICAgICAgICkpCgpuYW1lcyh4MF9tZXRhKSA8LSB1bmxpc3QobGFwcGx5KHNlcV9sZW4oVSksIGZ1bmN0aW9uKHgpIHBhc3RlMChjKCJTIiwiRSIsIkkiLCAiUiIsICJOIiksIHgpKSkKCiAgb3V0XzEwMF9tZXRhXzEyMCA8LSBzc2EoCiAgICB4MCA9IHgwX21ldGEsCiAgICBhID0gYV9tZXRhLAogICAgbnUgPSBudV9tZXRhLAogICAgcGFybXMgPSBwYXJtc19tZXRhXzEyMCwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhX21ldGFfMTIwIDwtIG91dF8xMDBfbWV0YV8xMjAkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHNlcGFyYXRlKElELCAKICAgICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3RhdGUsIHZhbHVlc19mcm9tID0gY291bnQpICU+JQogICAgbXV0YXRlKHBlcnNpc3QgPSBjYXNlX3doZW4oSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEkgPT0gMCB+IEYpLAogICAgICAgICAgIHNpbSA9IGkpICU+JQogICAgc2VsZWN0KHNpbSwgcGF0Y2gsIEksIE4sIHBlcnNpc3QpCiAgCiAgc2ltX2xpc3RfbWV0YV8xMjBbW2ldXSA8LSBzaW1fZGF0YV9tZXRhXzEyMAp9CgpzaW1fb3V0cHV0X21ldGFfMTIwIDwtIGJpbmRfcm93cyhzaW1fbGlzdF9tZXRhXzEyMCkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF9tZXRhXzEyMCA8LSBzaW1fb3V0cHV0X21ldGFfMTIwICU+JQogIGdyb3VwX2J5KHNpbSkgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX0kgPSBzdW0oSSksIAogICAgICAgICAgICB0b3RhbF9OID0gc3VtKE4pKSAlPiUKICBtdXRhdGUocGVyY2VudF9wZXJzaXN0ID0gdG90YWxfSS8odG90YWxfTikqMTAwLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHRvdGFsX0kgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9JID09IDAgfiBGKSkKc2ltX291dHB1dF9tZXRhXzEyMAoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5X21ldGFfMTIwIDwtIHNpbV9vdXRwdXRfbWV0YV8xMjAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QsIG5hLnJtID0gVCkvbnVtX3NpbXMpKjEwMCwgICAgICAgICAgICAgIG1lYW5fcGVyY2VudF9pbmZlY3RlZCA9IG1lYW4ocGVyY2VudF9wZXJzaXN0KSkgJT4lCiAgbXV0YXRlKG9tZWdhID0gMS8xMjApCnNpbV9zdW1tYXJ5X21ldGFfMTIwCmBgYAoKIyMjIyAxMzAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc19tZXRhXzEzMCA8LSBwYXJtc19tZXRhCnBhcm1zX21ldGFfMTMwJG9tZWdhIDwtIDEvMTMwCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfbWV0YV8xMzAgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGFfMTMwLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhX21ldGFfMTMwIDwtIG91dF9tZXRhXzEzMCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfbWV0YV8xMzAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfbWV0YV8xMzAsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGZhY2V0X3dyYXAofmZhY3RvcihwYXRjaCwgbGV2ZWxzID0gdW5pcXVlKHBhdGNoKSkgLG5jb2wgPSAzLCBzY2FsZXMgPSAiZnJlZV95IikrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF9tZXRhXzEzMApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0X21ldGFfMTMwIDwtIGxpc3QoKQpzaW1fbGlzdF9tZXRhXzEzMCA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIHBhdGNoUG9wU2l6ZSA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgNywgcmVwbGFjZSA9IFRSVUUpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICB4MF9tZXRhIDwtIHVubGlzdCgKICAgICAgbGFwcGx5KAogICAgICAgIHNlcV9sZW4oVSksCiAgICAgICAgZnVuY3Rpb24oeCl7CiAgICAgICAgICBjKHBhdGNoUG9wU2l6ZVt4XSAtIGluaXRpYWxfaW5mZWN0ZWRbeF0sIGluaXRpYWxfaW5mZWN0ZWRbeF0sIDAsIDAsIHBhdGNoUG9wU2l6ZVt4XSkKICAgICAgICAgIH0KICAgICAgICApKQoKbmFtZXMoeDBfbWV0YSkgPC0gdW5saXN0KGxhcHBseShzZXFfbGVuKFUpLCBmdW5jdGlvbih4KSBwYXN0ZTAoYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpLCB4KSkpCgogIG91dF8xMDBfbWV0YV8xMzAgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YV8xMzAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV9tZXRhXzEzMCA8LSBvdXRfMTAwX21ldGFfMTMwJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFfMTMwW1tpXV0gPC0gc2ltX2RhdGFfbWV0YV8xMzAKfQoKc2ltX291dHB1dF9tZXRhXzEzMCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YV8xMzApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfbWV0YV8xMzAgPC0gc2ltX291dHB1dF9tZXRhXzEzMCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfbWV0YV8xMzAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV9tZXRhXzEzMCA8LSBzaW1fb3V0cHV0X21ldGFfMTMwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvMTMwKQpzaW1fc3VtbWFyeV9tZXRhXzEzMApgYGAKCgoKCgoKCgoKCgoKIyMjIyAxNTAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc19tZXRhXzE1MCA8LSBwYXJtc19tZXRhCnBhcm1zX21ldGFfMTUwJG9tZWdhIDwtIDEvMTUwCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfbWV0YV8xNTAgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGFfMTUwLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhX21ldGFfMTUwIDwtIG91dF9tZXRhXzE1MCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfbWV0YV8xNTAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfbWV0YV8xNTAsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGZhY2V0X3dyYXAofmZhY3RvcihwYXRjaCwgbGV2ZWxzID0gdW5pcXVlKHBhdGNoKSkgLG5jb2wgPSAzLCBzY2FsZXMgPSAiZnJlZV95IikrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF9tZXRhXzE1MApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0X21ldGFfMTUwIDwtIGxpc3QoKQpzaW1fbGlzdF9tZXRhXzE1MCA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIHBhdGNoUG9wU2l6ZSA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgNywgcmVwbGFjZSA9IFRSVUUpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICB4MF9tZXRhIDwtIHVubGlzdCgKICAgICAgbGFwcGx5KAogICAgICAgIHNlcV9sZW4oVSksCiAgICAgICAgZnVuY3Rpb24oeCl7CiAgICAgICAgICBjKHBhdGNoUG9wU2l6ZVt4XSAtIGluaXRpYWxfaW5mZWN0ZWRbeF0sIGluaXRpYWxfaW5mZWN0ZWRbeF0sIDAsIDAsIHBhdGNoUG9wU2l6ZVt4XSkKICAgICAgICAgIH0KICAgICAgICApKQoKbmFtZXMoeDBfbWV0YSkgPC0gdW5saXN0KGxhcHBseShzZXFfbGVuKFUpLCBmdW5jdGlvbih4KSBwYXN0ZTAoYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpLCB4KSkpCgogIG91dF8xMDBfbWV0YV8xNTAgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YV8xNTAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV9tZXRhXzE1MCA8LSBvdXRfMTAwX21ldGFfMTUwJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFfMTUwW1tpXV0gPC0gc2ltX2RhdGFfbWV0YV8xNTAKfQoKc2ltX291dHB1dF9tZXRhXzE1MCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YV8xNTApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfbWV0YV8xNTAgPC0gc2ltX291dHB1dF9tZXRhXzE1MCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfbWV0YV8xNTAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV9tZXRhXzE1MCA8LSBzaW1fb3V0cHV0X21ldGFfMTUwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvMTUwKQpzaW1fc3VtbWFyeV9tZXRhXzE1MApgYGAKCgojIyMjIDIyMCBEYXlzCmBgYHtyfQojQ29sbGVjdCBwYXJhbWV0ZXJzCnBhcm1zX21ldGFfMjIwIDwtIHBhcm1zX21ldGEKcGFybXNfbWV0YV8yMjAkb21lZ2EgPC0gMS8yMjAKCgojIFJ1biBzaW11bGF0aW9ucyB3aXRoIHRoZSBEaXJlY3QgbWV0aG9kCnNldC5zZWVkKDQpCm91dF9tZXRhXzIyMCA8LSBzc2EoCiAgeDAgPSB4MF9tZXRhLAogIGEgPSBhX21ldGEsCiAgbnUgPSBudV9tZXRhLAogIHBhcm1zID0gcGFybXNfbWV0YV8yMjAsCiAgdGYgPSB0ZiwKICBtZXRob2QgPSBzc2EuZCgpLAogIHNpbU5hbWUgPSBzaW1OYW1lLAogIHZlcmJvc2UgPSBGQUxTRSwKICBjb25zb2xlSW50ZXJ2YWwgPSAxCikKCgojIyBFeHRyYSBQbG90cwpwbG90X2RhdGFfbWV0YV8yMjAgPC0gb3V0X21ldGFfMjIwJGRhdGEgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIHNlcGFyYXRlKElELCAKICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICBtdXRhdGUoc3RhdGUgPSBmYWN0b3Ioc3RhdGUsIGxldmVscyA9IGMoIlMiLCAiRSIsICJJIiwgIlIiLCAiTiIpKSkgIyU+JQogICNmaWx0ZXIoc3RhdGUgIT0gIk4iKQoKcGxvdF9tZXRhXzIyMCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RfZGF0YV9tZXRhXzIyMCwgYWVzKHg9dCwgeT1jb3VudCwgY29sb3VyPXN0YXRlKSkrCiAgZ2VvbV9saW5lKCkrCiAgZmFjZXRfd3JhcCh+ZmFjdG9yKHBhdGNoLCBsZXZlbHMgPSB1bmlxdWUocGF0Y2gpKSAsbmNvbCA9IDMsIHNjYWxlcyA9ICJmcmVlX3kiKSsKICBsYWJzKHg9IlRpbWUiLAogICAgICAgeT0iRnJlcXVlbmN5IikrCiAgdGhlbWVfYncoKQpwbG90X21ldGFfMjIwCmBgYApgYGB7cn0KIyMgUnVuIG11bHRpcGxlIHNpbXVsYXRpb25zIGFuZCBzYXZpbmcgb3V0cHV0Cm51bV9zaW1zIDwtIDEwMDAKc2ltX2xpc3RfbWV0YV8yMjAgPC0gbGlzdCgpCnNpbV9saXN0X21ldGFfMjIwIDwtIHZlY3RvcigibGlzdCIsIGxlbmd0aCA9IG51bV9zaW1zKQoKZm9yIChpIGluIDE6bnVtX3NpbXMpewogIHNldC5zZWVkKGkpCiAgCiAgcGF0Y2hQb3BTaXplIDwtICAgICBzYW1wbGUoY2FtcHMuZGF0YSRjYW1wX3RvdGFsLCA3LCByZXBsYWNlID0gVFJVRSkgICAgIyBTYW1wbGUgZGlmZmVyZW50IHBhdGNoIHNpemVzIGZvciBlYWNoIHNpbQogIHgwX21ldGEgPC0gdW5saXN0KAogICAgICBsYXBwbHkoCiAgICAgICAgc2VxX2xlbihVKSwKICAgICAgICBmdW5jdGlvbih4KXsKICAgICAgICAgIGMocGF0Y2hQb3BTaXplW3hdIC0gaW5pdGlhbF9pbmZlY3RlZFt4XSwgaW5pdGlhbF9pbmZlY3RlZFt4XSwgMCwgMCwgcGF0Y2hQb3BTaXplW3hdKQogICAgICAgICAgfQogICAgICAgICkpCgpuYW1lcyh4MF9tZXRhKSA8LSB1bmxpc3QobGFwcGx5KHNlcV9sZW4oVSksIGZ1bmN0aW9uKHgpIHBhc3RlMChjKCJTIiwiRSIsIkkiLCAiUiIsICJOIiksIHgpKSkKCiAgb3V0XzEwMF9tZXRhXzIyMCA8LSBzc2EoCiAgICB4MCA9IHgwX21ldGEsCiAgICBhID0gYV9tZXRhLAogICAgbnUgPSBudV9tZXRhLAogICAgcGFybXMgPSBwYXJtc19tZXRhXzIyMCwKICAgIHRmID0gdGYsCiAgICBtZXRob2QgPSBzc2EuZCgpLAogICAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgICB2ZXJib3NlID0gRkFMU0UsCiAgICBjb25zb2xlSW50ZXJ2YWwgPSAxCiAgKQoKICAKIyBFeHRyYWN0IEZpbmFsIHRpbWUgcG9pbnQgZnJvbSBvdXRwdXQgZGF0YQogIHNpbV9kYXRhX21ldGFfMjIwIDwtIG91dF8xMDBfbWV0YV8yMjAkZGF0YSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgc2xpY2VfbWF4KHQpICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICAgIHNlcGFyYXRlKElELCAKICAgICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3RhdGUsIHZhbHVlc19mcm9tID0gY291bnQpICU+JQogICAgbXV0YXRlKHBlcnNpc3QgPSBjYXNlX3doZW4oSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEkgPT0gMCB+IEYpLAogICAgICAgICAgIHNpbSA9IGkpICU+JQogICAgc2VsZWN0KHNpbSwgcGF0Y2gsIEksIE4sIHBlcnNpc3QpCiAgCiAgc2ltX2xpc3RfbWV0YV8yMjBbW2ldXSA8LSBzaW1fZGF0YV9tZXRhXzIyMAp9CgpzaW1fb3V0cHV0X21ldGFfMjIwIDwtIGJpbmRfcm93cyhzaW1fbGlzdF9tZXRhXzIyMCkKYGBgCgpgYGB7cn0KIyBTdW1tYXJ5IHRhYmxlIG9mIGVuZHBvaW50IGRhdGEKc2ltX291dHB1dF9tZXRhXzIyMCA8LSBzaW1fb3V0cHV0X21ldGFfMjIwICU+JQogIGdyb3VwX2J5KHNpbSkgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX0kgPSBzdW0oSSksIAogICAgICAgICAgICB0b3RhbF9OID0gc3VtKE4pKSAlPiUKICBtdXRhdGUocGVyY2VudF9wZXJzaXN0ID0gdG90YWxfSS8odG90YWxfTikqMTAwLAogICAgICAgICBwZXJzaXN0ID0gY2FzZV93aGVuKHRvdGFsX0kgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9JID09IDAgfiBGKSkKc2ltX291dHB1dF9tZXRhXzIyMAoKIyBNYWtlIFN1bW1hcnkgVGFibGUgb2Ygb3V0cHV0CnNpbV9zdW1tYXJ5X21ldGFfMjIwIDwtIHNpbV9vdXRwdXRfbWV0YV8yMjAgJT4lCiAgc3VtbWFyaXNlKG1lYW5faW5mZWN0ZWRzID0gbWVhbih0b3RhbF9JKSwKICAgICAgICAgICAgc3VtX3BlcnNpc3QgPSAoc3VtKHBlcnNpc3QsIG5hLnJtID0gVCkvbnVtX3NpbXMpKjEwMCwgICAgICAgICAgICAgIG1lYW5fcGVyY2VudF9pbmZlY3RlZCA9IG1lYW4ocGVyY2VudF9wZXJzaXN0KSkgJT4lCiAgbXV0YXRlKG9tZWdhID0gMS8yMjApCnNpbV9zdW1tYXJ5X21ldGFfMjIwCmBgYAoKCgoKIyMjIyAyNzAgRGF5cwpgYGB7cn0KI0NvbGxlY3QgcGFyYW1ldGVycwpwYXJtc19tZXRhXzI3MCA8LSBwYXJtc19tZXRhCnBhcm1zX21ldGFfMjcwJG9tZWdhIDwtIDEvMjcwCgoKIyBSdW4gc2ltdWxhdGlvbnMgd2l0aCB0aGUgRGlyZWN0IG1ldGhvZApzZXQuc2VlZCg0KQpvdXRfbWV0YV8yNzAgPC0gc3NhKAogIHgwID0geDBfbWV0YSwKICBhID0gYV9tZXRhLAogIG51ID0gbnVfbWV0YSwKICBwYXJtcyA9IHBhcm1zX21ldGFfMjcwLAogIHRmID0gdGYsCiAgbWV0aG9kID0gc3NhLmQoKSwKICBzaW1OYW1lID0gc2ltTmFtZSwKICB2ZXJib3NlID0gRkFMU0UsCiAgY29uc29sZUludGVydmFsID0gMQopCgoKIyMgRXh0cmEgUGxvdHMKcGxvdF9kYXRhX21ldGFfMjcwIDwtIG91dF9tZXRhXzI3MCRkYXRhICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHBpdm90X2xvbmdlcighdCwgbmFtZXNfdG8gPSAiSUQiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUKICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgIHNlcCA9ICIoPzw9W0EtWmEtel0pKD89WzAtOV0pIikgJT4lCiAgbXV0YXRlKHN0YXRlID0gZmFjdG9yKHN0YXRlLCBsZXZlbHMgPSBjKCJTIiwgIkUiLCAiSSIsICJSIiwgIk4iKSkpICMlPiUKICAjZmlsdGVyKHN0YXRlICE9ICJOIikKCnBsb3RfbWV0YV8yNzAgPC0gZ2dwbG90KGRhdGEgPSBwbG90X2RhdGFfbWV0YV8yNzAsIGFlcyh4PXQsIHk9Y291bnQsIGNvbG91cj1zdGF0ZSkpKwogIGdlb21fbGluZSgpKwogIGZhY2V0X3dyYXAofmZhY3RvcihwYXRjaCwgbGV2ZWxzID0gdW5pcXVlKHBhdGNoKSkgLG5jb2wgPSAzLCBzY2FsZXMgPSAiZnJlZV95IikrCiAgbGFicyh4PSJUaW1lIiwKICAgICAgIHk9IkZyZXF1ZW5jeSIpKwogIHRoZW1lX2J3KCkKcGxvdF9tZXRhXzI3MApgYGAKYGBge3J9CiMjIFJ1biBtdWx0aXBsZSBzaW11bGF0aW9ucyBhbmQgc2F2aW5nIG91dHB1dApudW1fc2ltcyA8LSAxMDAwCnNpbV9saXN0X21ldGFfMjcwIDwtIGxpc3QoKQpzaW1fbGlzdF9tZXRhXzI3MCA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBudW1fc2ltcykKCmZvciAoaSBpbiAxOm51bV9zaW1zKXsKICBzZXQuc2VlZChpKQogIAogIHBhdGNoUG9wU2l6ZSA8LSAgICAgc2FtcGxlKGNhbXBzLmRhdGEkY2FtcF90b3RhbCwgNywgcmVwbGFjZSA9IFRSVUUpICAgICMgU2FtcGxlIGRpZmZlcmVudCBwYXRjaCBzaXplcyBmb3IgZWFjaCBzaW0KICB4MF9tZXRhIDwtIHVubGlzdCgKICAgICAgbGFwcGx5KAogICAgICAgIHNlcV9sZW4oVSksCiAgICAgICAgZnVuY3Rpb24oeCl7CiAgICAgICAgICBjKHBhdGNoUG9wU2l6ZVt4XSAtIGluaXRpYWxfaW5mZWN0ZWRbeF0sIGluaXRpYWxfaW5mZWN0ZWRbeF0sIDAsIDAsIHBhdGNoUG9wU2l6ZVt4XSkKICAgICAgICAgIH0KICAgICAgICApKQoKbmFtZXMoeDBfbWV0YSkgPC0gdW5saXN0KGxhcHBseShzZXFfbGVuKFUpLCBmdW5jdGlvbih4KSBwYXN0ZTAoYygiUyIsIkUiLCJJIiwgIlIiLCAiTiIpLCB4KSkpCgogIG91dF8xMDBfbWV0YV8yNzAgPC0gc3NhKAogICAgeDAgPSB4MF9tZXRhLAogICAgYSA9IGFfbWV0YSwKICAgIG51ID0gbnVfbWV0YSwKICAgIHBhcm1zID0gcGFybXNfbWV0YV8yNzAsCiAgICB0ZiA9IHRmLAogICAgbWV0aG9kID0gc3NhLmQoKSwKICAgIHNpbU5hbWUgPSBzaW1OYW1lLAogICAgdmVyYm9zZSA9IEZBTFNFLAogICAgY29uc29sZUludGVydmFsID0gMQogICkKCiAgCiMgRXh0cmFjdCBGaW5hbCB0aW1lIHBvaW50IGZyb20gb3V0cHV0IGRhdGEKICBzaW1fZGF0YV9tZXRhXzI3MCA8LSBvdXRfMTAwX21ldGFfMjcwJGRhdGEgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHNsaWNlX21heCh0KSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgICBzZXBhcmF0ZShJRCwgCiAgICAgICAgICAgICBpbnRvID0gYygic3RhdGUiLCAicGF0Y2giKSwgCiAgICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRlLCB2YWx1ZXNfZnJvbSA9IGNvdW50KSAlPiUKICAgIG11dGF0ZShwZXJzaXN0ID0gY2FzZV93aGVuKEkgPiAwIH4gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJID09IDAgfiBGKSwKICAgICAgICAgICBzaW0gPSBpKSAlPiUKICAgIHNlbGVjdChzaW0sIHBhdGNoLCBJLCBOLCBwZXJzaXN0KQogIAogIHNpbV9saXN0X21ldGFfMjcwW1tpXV0gPC0gc2ltX2RhdGFfbWV0YV8yNzAKfQoKc2ltX291dHB1dF9tZXRhXzI3MCA8LSBiaW5kX3Jvd3Moc2ltX2xpc3RfbWV0YV8yNzApCmBgYAoKYGBge3J9CiMgU3VtbWFyeSB0YWJsZSBvZiBlbmRwb2ludCBkYXRhCnNpbV9vdXRwdXRfbWV0YV8yNzAgPC0gc2ltX291dHB1dF9tZXRhXzI3MCAlPiUKICBncm91cF9ieShzaW0pICU+JQogIHN1bW1hcmlzZSh0b3RhbF9JID0gc3VtKEkpLCAKICAgICAgICAgICAgdG90YWxfTiA9IHN1bShOKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRfcGVyc2lzdCA9IHRvdGFsX0kvKHRvdGFsX04pKjEwMCwKICAgICAgICAgcGVyc2lzdCA9IGNhc2Vfd2hlbih0b3RhbF9JID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfSSA9PSAwIH4gRikpCnNpbV9vdXRwdXRfbWV0YV8yNzAKCiMgTWFrZSBTdW1tYXJ5IFRhYmxlIG9mIG91dHB1dApzaW1fc3VtbWFyeV9tZXRhXzI3MCA8LSBzaW1fb3V0cHV0X21ldGFfMjcwICU+JQogIHN1bW1hcmlzZShtZWFuX2luZmVjdGVkcyA9IG1lYW4odG90YWxfSSksCiAgICAgICAgICAgIHN1bV9wZXJzaXN0ID0gKHN1bShwZXJzaXN0LCBuYS5ybSA9IFQpL251bV9zaW1zKSoxMDAsICAgICAgICAgICAgICBtZWFuX3BlcmNlbnRfaW5mZWN0ZWQgPSBtZWFuKHBlcmNlbnRfcGVyc2lzdCkpICU+JQogIG11dGF0ZShvbWVnYSA9IDEvMjcwKQpzaW1fc3VtbWFyeV9tZXRhXzI3MApgYGAKCiMjIyMgMzY1IERheXMKYGBge3J9CiNDb2xsZWN0IHBhcmFtZXRlcnMKcGFybXNfbWV0YV8zNjUgPC0gcGFybXNfbWV0YQpwYXJtc19tZXRhXzM2NSRvbWVnYSA8LSAxLzM2NQoKCiMgUnVuIHNpbXVsYXRpb25zIHdpdGggdGhlIERpcmVjdCBtZXRob2QKc2V0LnNlZWQoNCkKb3V0X21ldGFfMzY1IDwtIHNzYSgKICB4MCA9IHgwX21ldGEsCiAgYSA9IGFfbWV0YSwKICBudSA9IG51X21ldGEsCiAgcGFybXMgPSBwYXJtc19tZXRhXzM2NSwKICB0ZiA9IHRmLAogIG1ldGhvZCA9IHNzYS5kKCksCiAgc2ltTmFtZSA9IHNpbU5hbWUsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGNvbnNvbGVJbnRlcnZhbCA9IDEKKQoKCiMjIEV4dHJhIFBsb3RzCnBsb3RfZGF0YV9tZXRhXzM2NSA8LSBvdXRfbWV0YV8zNjUkZGF0YSAlPiUKICBhc190aWJibGUoKSAlPiUKICBwaXZvdF9sb25nZXIoIXQsIG5hbWVzX3RvID0gIklEIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lCiAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgIGludG8gPSBjKCJzdGF0ZSIsICJwYXRjaCIpLCAKICAgICAgICAgICBzZXAgPSAiKD88PVtBLVphLXpdKSg/PVswLTldKSIpICU+JQogIG11dGF0ZShzdGF0ZSA9IGZhY3RvcihzdGF0ZSwgbGV2ZWxzID0gYygiUyIsICJFIiwgIkkiLCAiUiIsICJOIikpKSAjJT4lCiAgI2ZpbHRlcihzdGF0ZSAhPSAiTiIpCgpwbG90X21ldGFfMzY1IDwtIGdncGxvdChkYXRhID0gcGxvdF9kYXRhX21ldGFfMzY1LCBhZXMoeD10LCB5PWNvdW50LCBjb2xvdXI9c3RhdGUpKSsKICBnZW9tX2xpbmUoKSsKICBmYWNldF93cmFwKH5mYWN0b3IocGF0Y2gsIGxldmVscyA9IHVuaXF1ZShwYXRjaCkpICxuY29sID0gMywgc2NhbGVzID0gImZyZWVfeSIpKwogIGxhYnMoeD0iVGltZSIsCiAgICAgICB5PSJGcmVxdWVuY3kiKSsKICB0aGVtZV9idygpCnBsb3RfbWV0YV8zNjUKYGBgCmBgYHtyfQojIyBSdW4gbXVsdGlwbGUgc2ltdWxhdGlvbnMgYW5kIHNhdmluZyBvdXRwdXQKbnVtX3NpbXMgPC0gMTAwMApzaW1fbGlzdF9tZXRhXzM2NSA8LSBsaXN0KCkKc2ltX2xpc3RfbWV0YV8zNjUgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gbnVtX3NpbXMpCgpmb3IgKGkgaW4gMTpudW1fc2ltcyl7CiAgc2V0LnNlZWQoaSkKICAKICBwYXRjaFBvcFNpemUgPC0gICAgIHNhbXBsZShjYW1wcy5kYXRhJGNhbXBfdG90YWwsIDcsIHJlcGxhY2UgPSBUUlVFKSAgICAjIFNhbXBsZSBkaWZmZXJlbnQgcGF0Y2ggc2l6ZXMgZm9yIGVhY2ggc2ltCiAgeDBfbWV0YSA8LSB1bmxpc3QoCiAgICAgIGxhcHBseSgKICAgICAgICBzZXFfbGVuKFUpLAogICAgICAgIGZ1bmN0aW9uKHgpewogICAgICAgICAgYyhwYXRjaFBvcFNpemVbeF0gLSBpbml0aWFsX2luZmVjdGVkW3hdLCBpbml0aWFsX2luZmVjdGVkW3hdLCAwLCAwLCBwYXRjaFBvcFNpemVbeF0pCiAgICAgICAgICB9CiAgICAgICAgKSkKCm5hbWVzKHgwX21ldGEpIDwtIHVubGlzdChsYXBwbHkoc2VxX2xlbihVKSwgZnVuY3Rpb24oeCkgcGFzdGUwKGMoIlMiLCJFIiwiSSIsICJSIiwgIk4iKSwgeCkpKQoKICBvdXRfMTAwX21ldGFfMzY1IDwtIHNzYSgKICAgIHgwID0geDBfbWV0YSwKICAgIGEgPSBhX21ldGEsCiAgICBudSA9IG51X21ldGEsCiAgICBwYXJtcyA9IHBhcm1zX21ldGFfMzY1LAogICAgdGYgPSB0ZiwKICAgIG1ldGhvZCA9IHNzYS5kKCksCiAgICBzaW1OYW1lID0gc2ltTmFtZSwKICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgIGNvbnNvbGVJbnRlcnZhbCA9IDEKICApCgogIAojIEV4dHJhY3QgRmluYWwgdGltZSBwb2ludCBmcm9tIG91dHB1dCBkYXRhCiAgc2ltX2RhdGFfbWV0YV8zNjUgPC0gb3V0XzEwMF9tZXRhXzM2NSRkYXRhICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBzbGljZV9tYXgodCkgJT4lCiAgICBkaXN0aW5jdCgpICU+JQogICAgcGl2b3RfbG9uZ2VyKCF0LCBuYW1lc190byA9ICJJRCIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogICAgc2VwYXJhdGUoSUQsIAogICAgICAgICAgICAgaW50byA9IGMoInN0YXRlIiwgInBhdGNoIiksIAogICAgICAgICAgICAgc2VwID0gIig/PD1bQS1aYS16XSkoPz1bMC05XSkiKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGF0ZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkgJT4lCiAgICBtdXRhdGUocGVyc2lzdCA9IGNhc2Vfd2hlbihJID4gMCB+IFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9PSAwIH4gRiksCiAgICAgICAgICAgc2ltID0gaSkgJT4lCiAgICBzZWxlY3Qoc2ltLCBwYXRjaCwgSSwgTiwgcGVyc2lzdCkKICAKICBzaW1fbGlzdF9tZXRhXzM2NVtbaV1dIDwtIHNpbV9kYXRhX21ldGFfMzY1Cn0KCnNpbV9vdXRwdXRfbWV0YV8zNjUgPC0gYmluZF9yb3dzKHNpbV9saXN0X21ldGFfMzY1KQpgYGAKCmBgYHtyfQojIFN1bW1hcnkgdGFibGUgb2YgZW5kcG9pbnQgZGF0YQpzaW1fb3V0cHV0X21ldGFfMzY1IDwtIHNpbV9vdXRwdXRfbWV0YV8zNjUgJT4lCiAgZ3JvdXBfYnkoc2ltKSAlPiUKICBzdW1tYXJpc2UodG90YWxfSSA9IHN1bShJKSwgCiAgICAgICAgICAgIHRvdGFsX04gPSBzdW0oTikpICU+JQogIG11dGF0ZShwZXJjZW50X3BlcnNpc3QgPSB0b3RhbF9JLyh0b3RhbF9OKSoxMDAsCiAgICAgICAgIHBlcnNpc3QgPSBjYXNlX3doZW4odG90YWxfSSA+IDAgfiBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsX0kgPT0gMCB+IEYpKQpzaW1fb3V0cHV0X21ldGFfMzY1CgojIE1ha2UgU3VtbWFyeSBUYWJsZSBvZiBvdXRwdXQKc2ltX3N1bW1hcnlfbWV0YV8zNjUgPC0gc2ltX291dHB1dF9tZXRhXzM2NSAlPiUKICBzdW1tYXJpc2UobWVhbl9pbmZlY3RlZHMgPSBtZWFuKHRvdGFsX0kpLAogICAgICAgICAgICBzdW1fcGVyc2lzdCA9IChzdW0ocGVyc2lzdCwgbmEucm0gPSBUKS9udW1fc2ltcykqMTAwLCAgICAgICAgICAgICAgbWVhbl9wZXJjZW50X2luZmVjdGVkID0gbWVhbihwZXJjZW50X3BlcnNpc3QpKSAlPiUKICBtdXRhdGUob21lZ2EgPSAxLzM2NSkKc2ltX3N1bW1hcnlfbWV0YV8zNjUKYGBgCgpTaW5nbGUKCgoKCgojIyMjIFJlc3VsdHMKYGBge3J9CndhbmluZ19yZXN1bHRzIDwtIHNpbV9zdW1tYXJ5X21ldGEgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5X21ldGFfMykgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5X21ldGFfNykgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5X21ldGFfMTApICU+JQogIGJpbmRfcm93cyhzaW1fc3VtbWFyeV9tZXRhXzIwKSAlPiUKICBiaW5kX3Jvd3Moc2ltX3N1bW1hcnlfbWV0YV8zMCkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5X21ldGFfNDApICU+JQogIGJpbmRfcm93cyhzaW1fc3VtbWFyeV9tZXRhXzUwKSAlPiUKICBiaW5kX3Jvd3Moc2ltX3N1bW1hcnlfbWV0YV82MCkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5X21ldGFfNzApICU+JQogIGJpbmRfcm93cyhzaW1fc3VtbWFyeV9tZXRhXzgwKSAlPiUKICBiaW5kX3Jvd3Moc2ltX3N1bW1hcnlfbWV0YV85MCkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5X21ldGFfMTAwKSAlPiUKICBiaW5kX3Jvd3Moc2ltX3N1bW1hcnlfbWV0YV8xMTApICU+JQogIGJpbmRfcm93cyhzaW1fc3VtbWFyeV9tZXRhXzEyMCkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5X21ldGFfMTMwKSAlPiUKICBiaW5kX3Jvd3Moc2ltX3N1bW1hcnlfbWV0YV8xNTApICU+JQogIGJpbmRfcm93cyhzaW1fc3VtbWFyeV9tZXRhXzIyMCkgJT4lCiAgYmluZF9yb3dzKHNpbV9zdW1tYXJ5X21ldGFfMjcwKSAlPiUKICBiaW5kX3Jvd3Moc2ltX3N1bW1hcnlfbWV0YV8zNjUpICU+JQogIG11dGF0ZShpbW11bml0eV9kdXJhdGlvbiA9IDEvb21lZ2EpICU+JQogIGFycmFuZ2UoaW1tdW5pdHlfZHVyYXRpb24pICU+JQogIG11dGF0ZShtb2RlbCA9ICJtZXRhIikKCndyaXRlX2Nzdih3YW5pbmdfcmVzdWx0cywgZmlsZSA9ICIvVXNlcnMvbWF0dGhld2hveWxlL0dpdGh1Yl9SX3Byb2plY3RzL0h1bnRlcl9HYXRoZXJlcl9tb2RlbHMvd2FuaW5nX3Jlc3VsdHMuY3N2IikKCndhbmluZ19yZXN1bHRzCgpgYGAKCmBgYHtyfQpnZ3Bsb3Qod2FuaW5nX3Jlc3VsdHMsIGFlcyhpbW11bml0eV9kdXJhdGlvbiwgc3VtX3BlcnNpc3QpKSArCiAgZ2VvbV9saW5lKCkrCiAgZ2VvbV9wb2ludCgpKwogIHRoZW1lX2J3KCkKYGBgCgoKCiMjIENvbWJpbmVkIFJlc3VsdHMKYGBge3J9CmNvbWJpbmVkX3dhbmluZyA8LSB3YW5pbmdfcmVzdWx0cyAlPiUKICBiaW5kX3Jvd3Mod2FuaW5nX3Jlc3VsdHNfc2luZ2xlKQoKY29tYmluZWRfd2FuaW5nCgp3cml0ZV9jc3YoY29tYmluZWRfd2FuaW5nLCBmaWxlID0gIi9Vc2Vycy9tYXR0aGV3aG95bGUvR2l0aHViX1JfcHJvamVjdHMvSHVudGVyX0dhdGhlcmVyX21vZGVscy9jb21iaW5lZF93YW5pbmdfcmVzdWx0cy5jc3YiKQpgYGAKCgpgYGB7cn0KY29tYmluZWRfcGxvdCA8LSBnZ3Bsb3QoY29tYmluZWRfd2FuaW5nLCBhZXMoaW1tdW5pdHlfZHVyYXRpb24sIHN1bV9wZXJzaXN0LCBjb2xvdXIgPSBtb2RlbCkpKwogIGdlb21fbGluZSgpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3NlZ21lbnQoeCA9IC1JbmYsIHkgPSA1MCwgeGVuZCA9IDkxLjUsIHllbmQgPSA1MCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3VyID0gImdyZXkiKSArCiAgZ2VvbV9zZWdtZW50KHggPSA1LCB5ID0gNTAsIHhlbmQgPSA1LCB5ZW5kID0gLUluZiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3VyID0gImdyZXkiKSArCiAgZ2VvbV9zZWdtZW50KHggPSA5MS41LCB5ID0gNTAsIHhlbmQgPSA5MS41LCB5ZW5kID0gLUluZiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3VyID0gImdyZXkiKSArCiAgbGFicyh4ID0gIkR1cmF0aW9uIG9mIGltbXVuaXR5IiwKICAgICAgIHkgPSAiUHJvYmFiaWxpdHkgb2YgcGVyc2lzdGVuY2UgYWZ0ZXIgMyB5ZWFycyAoJSkiLCAKICAgICAgIGNvbG91ciA9ICJNb2RlbCBUeXBlIikrCiAgc2NhbGVfY29sb3JfZGlzY3JldGUodHlwZSA9IHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMSIsIHR5cGUgPSAiZGlzY3JldGUiKVsxOjJdLAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk1ldGFwb3B1bGF0aW9uIiwgIlNpbmdsZSBQb3B1bGF0aW9uIikpKwogIHRoZW1lX2J3KCkKCmNvbWJpbmVkX3Bsb3QKCmdnc2F2ZShmaWxlbmFtZSA9ICJjb21iaW5lZF9wbG90LnBkZiIsIAogICAgICAgcGxvdCA9IGNvbWJpbmVkX3Bsb3QsCiAgICAgICBkZXZpY2UgPSAicGRmIiwKICAgICAgIHdpZHRoID0gNywgCiAgICAgICBoZWlnaHQgPSA1LAogICAgICAgcGF0aCA9ICIvVXNlcnMvbWF0dGhld2hveWxlL0dpdGh1Yl9SX3Byb2plY3RzL0h1bnRlcl9HYXRoZXJlcl9tb2RlbHMiKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoY29tYmluZWRfd2FuaW5nLCBhZXMoaW1tdW5pdHlfZHVyYXRpb24sIG1lYW5fcGVyY2VudF9pbmZlY3RlZCwgY29sb3VyID0gbW9kZWwpKSsKICBnZW9tX2xpbmUoKSsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeCA9ICJEdXJhdGlvbiBvZiBpbW11bml0eSIsCiAgICAgICB5ID0gIlByb3BvcnRpb24gaW5mZWN0ZWQgYXQgZW5kcG9pbnQgKCUpIiwgCiAgICAgICBjb2xvdXIgPSAiTW9kZWwgVHlwZSIpKwogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKHR5cGUgPSB3ZXNfcGFsZXR0ZSgiRGFyamVlbGluZzEiLCB0eXBlID0gImRpc2NyZXRlIilbMToyXSwKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNZXRhcG9wdWxhdGlvbiIsICJTaW5nbGUgUG9wdWxhdGlvbiIpKSsKICB0aGVtZV9idygpCmBgYAoK